第 1 章 自动化测试

再好的程序员也会犯错。好程序员不同于差程序员之处在于他们通过测试来尽早发现错误。测试进行的越早,发现错误的机会就越大,发现和修正的代价就越小。因此临近软件发布才进行测试是很有问题的做法。大多数错误都未能发现,而已发现的那些错误,修正它们的代价实在太大,于是根本不可能把它们全部修复,只能挑着处理其中的一部分。

使用 PHPUnit 进行测试与过往的做法并没有本质区别,只是方式有所不同。二者的区别在于测试执行一系列测试,前者检查软件的行为是否符合预期,后者则利用一些可运行的代码片段来自动测试软件各个部分(单元)的正确性。这些可运行的代码片段称为单元测试。

在本章中,我们将从基于 print 的简单测试代码开始,逐步前进至完全自动化的测试。假设我们需要对 PHP 内建的 array 进行测试。其中一个要测试的功能是 count() 函数。对于新建立的数组,我们预期 count() 函数将返回 0。添加一个元素之后,count() 函数应当返回 1例 1.1展示了我们要测试的东西。

例 1.1: 对数组操作进行测试

<?php
$fixture = array();
// $fixture 应当为空。

$fixture[] = 'element';
// $fixture 应当包含 1 个元素。
?>


要检查我们是否得到了预期的结果,简单的办法是在添加元素前后分别输出 count() 的结果(见例 1.2)。若前后分别得到 01,则 arraycount() 的行为符合预期。

例 1.2: 使用 print 测试数组操作

<?php
$fixture = array();
print count($fixture) . "\n";

$fixture[] = 'element';
print count($fixture) . "\n";
?>
0
1


现在,我们要把需要人工对结果进行解读的测试修改成能自动运行。在例 1.3中,我们在测试代码中加入了对预期值与实际值的比较,并且在两个值相等时输出 ok。一旦看到 not ok 讯息,我们就知道出错了。

例 1.3: 通过比较预期值与实际值来测试数组操作

<?php
$fixture = array();
print count($fixture) == 0 ? "ok\n" : "not ok\n";

$fixture[] = 'element';
print count($fixture) == 1 ? "ok\n" : "not ok\n";
?>
ok
ok


现在我们把对预期值和实际值进行比较的部分提取出来,成为独立的函数,在二个值存在差异时这个函数会抛出异常(例 1.4)。这有两个好处:编写测试更容易了,并且只在出错时产生输出。

例 1.4: 使用断言函数测试数组操作

<?php
ini_set('error_log', '');
ini_set('display_errors', 'Off');

$fixture = array();
assertTrue(count($fixture) == 0);

$fixture[] = 'element';
assertTrue(count($fixture) == 1);

function assertTrue($condition)
{
    if (!$condition) {
        throw new Exception('Assertion failed.');
    }
}
?>


现在测试完全自动化了。在第一个版本里我们只是简单的测试,而这个版本已经是自动测试

使用自动化测试的目的是少犯错。虽然说就算有了极好的测试你的代码也仍然无法达到完美,但是一旦开始进行自动化测试,你很可能会发现缺陷显著减少了。自动化测试让你对自己的代码有充分的信心。这种信心将让你能够在设计上做出更大胆的跨越(重构)、同团队成员们合作地更好(跨团队测试)、与客户之间的关系有所改善,并且在每天晚上回家时都能确信,自己的努力使系统比当天早上更好。

请在 GitHub 上 开启任务单 来对本页提出改进建议。万分感谢!