定义单元测试
单元测试是专门测试解决方案代码单元的程序。只需将其视为一个测试函数的程序,而不依赖于项目中的其他对象。
例如,如果您有一个名为 calculateTotal($a, $b, $c)
的函数,那么您可以为它编写一个名为 testCanCalculateTotal()
的单元测试函数。该单元测试的任务是根据项目规范中定义的业务规则,验证 calculateTotal($a, $b, $c)
函数是否返回预期结果。
在本例中,我们假设 calculateTotal
函数的预期行为是获取 $a
、$b
和 $c
三个参数的总和。
让我们创建一个单元测试示例和解决方案代码。在我们的开发容器中创建以下文件:
<?php
namespace App\Tests\Unit;
use App\Example\Calculator;
use PHPUnit\Framework\TestCase;
class CalculationTest extends TestCase
{
public function testCanCalculateTotal()
{
// Expected result:
$expectedTotal = 6;
// Test data:
$a = 1;
$b = 2;
$c = 3;
$calculator = new Calculator();
$total = $calculator->calculateTotal($a, $b, $c);
$this->assertEquals($expectedTotal, $total);
}
}
测试类名称需要以 Test
为后缀,它扩展了 PHPUnit\Framework\TestCase
类。通过这样做,我们现在正在使用 PHPUnit 库。
接下来,让我们尝试运行这个单元测试,看看会发生什么。在容器内运行以下命令。有关如何执行所有这些操作的说明请参见 第 3 章,使用 Docker 容器设置我们的开发环境:
/var/www/html/symfony# php bin/phpunit –filter testCanCalculateTotal
结果将是一个错误:

我们的单元测试如预期失败了——这很好!您会注意到我们试图实例化一个不存在的类,所以现在让我们创建该类并编写函数来进行计算。在我们之前创建的 codebase/symfony/src/Example/
目录中创建以下解决方案类:
<?php
namespace App\Example;
class Calculator
{
public function calculateTotal(int $a, int $b, int $c) : int
{
return $a + $b - $c;
}
}
使用 calculateTotal
函数创建解决方案类后,让我们尝试通过运行以下命令再次运行测试:
/var/www/html/symfony# php bin/phpunit –filter testCanCalculateTotal
我们将得到以下失败结果:

PHPUnit 会告诉我们测试失败的原因。您会注意到它显示:Failed asserting that 0 matches expected 6
。为什么会这样? 嗯,这就是发生的事情。
在 testCanCalculateTotal
单元测试中,我们已将 $expectedTotal
声明为 6
。然后,我们调用 calculateTotal
函数并发送以下参数:$a = 1
、$b = 2
和 $c = 3
。如果您收到的规范指示您获得 calculateTotal
函数中三个参数的总和,那么预期结果是 6
。
然后我们使用 assertEquals
PHPUnit 函数,我们告诉 PHPUnit 我们期望预期值将等于计算值,如下行所示:
$this->assertEquals($expectedTotal, $total);
断言是断言或检查测试中的条件是否满足的方法或函数。就像在我们的示例中,我们使用了 assertEquals
方法,尝试将 $expectedTotal
与我们从解决方案代码中收到的实际 $total
进行比较。PHPUnit 断言有很多不同类型,文档可在此处找到: https://phpunit.readthedocs.io/en/9.5/assertions.html 。
单元测试正确地期望预期结果为 6
- 问题是在解决方案函数中,我们没有遵循预期行为。我们将 $c
减去,而不是加到 $a
和 $b
的和中。如果我们将函数修改如下,测试就会最终通过:
public function calculateTotal(int $a, int $b, int $c) : int
{
return $a + $b + $c;
}
为了得到总数,我们只需要得到三个参数的总和。更新 Calculator.php
文件后,运行以下命令:
php bin/phpunit --filter testCanCalculateTotal
我们现在应该看到以下结果:

不错!我们终于通过了单元测试!assertEquals
函数确认了 $expectedTotal
现在等于解决方案代码返回的 $total
!
现在,想象一下有成千上万个这样的测试。如果解决方案代码的行为发生意外变化,就会导致一个或多个单元测试失败。这是非常有价值的。这将帮助开发人员验证他们实施的任何代码变更的稳定性。
要了解有关 PHPUnit 的更多信息,可访问其文档页面 https://phpunit.readthedocs.io/ 。
这是使用单元测试的最基本示例之一,但随着项目的继续,我们将编写更多的单元测试并使用更多的 PHPUnit 功能。
对解决方案代码的测试越多,解决方案的稳定性就越好。因此,接下来我们将研究 PHPUnit 的代码覆盖率分析解决方案。这将帮助我们了解解决方案的测试覆盖率。