编写第一个测试:测试类与测试方法命名规范、assert方法概览、运行测试
好,咱们现在开始动手写第一个测试。
说实话,很多初学者卡就卡在这一步——不是不会写代码,而是不知道「测试该长什么样」。我当年带团队时,有个同事写了三年 PHP,第一次写测试时居然把测试类命名成了 test.php。嗯,这当然也能跑,但团队里其他人看到会疯掉的。
测试类与测试方法的命名规范
先定规矩。PHPUnit 对命名有约定,说白了就是「望文生义」。
测试类的命名
- 类名必须以
Test结尾。比如UserServiceTest、OrderControllerTest - 类名通常对应被测试的类名。你测
UserService,测试类就叫UserServiceTest - 文件命名必须和类名一致,且放在
tests/目录下
我个人习惯:测试类名用「被测试类 + Test」这种模式。别搞什么花哨的 UserServiceTestCases 或者 TestUserService,团队里每个人看到 XxxTest 就知道这是测试文件。
测试方法的命名
方法名要能说清楚「测什么、什么场景、期望什么结果」。我推荐这种模式:
test[被测方法]_[场景]_[期望结果]
举个例子:
class UserServiceTest extends TestCase
{
public function testCreateUser_WithValidData_ReturnsUserId()
{
// 测试创建用户,传入合法数据,期望返回用户ID
}
public function testCreateUser_WithEmptyName_ThrowsException()
{
// 测试创建用户,传入空名字,期望抛出异常
}
}
你想想看,三个月后你回来看这段代码,是不是一眼就知道每个方法在测什么?
避坑指南:我曾经见过有人用中文写方法名,比如 test创建用户成功。虽然 PHP 允许,但 IDE 的自动补全和重构工具对中文支持很差。老老实实用英文驼峰命名吧。
assert 方法概览
测试的核心就是「断言」——判断实际结果和预期是否一致。PHPUnit 提供了几十种 assert 方法,但常用的其实就这几个:
| 方法 | 用途 | 示例 |
|---|---|---|
assertEquals() |
判断两个值是否相等(宽松比较) | $this->assertEquals(10, $result); |
assertSame() |
判断两个值是否全等(严格比较,类型也一致) | $this->assertSame(10, $result); |
assertTrue() |
判断是否为 true | $this->assertTrue($isValid); |
assertFalse() |
判断是否为 false | $this->assertFalse($hasError); |
assertNull() |
判断是否为 null | $this->assertNull($user); |
assertNotNull() |
判断是否不为 null | $this->assertNotNull($user); |
assertCount() |
判断数组或集合的元素个数 | $this->assertCount(3, $items); |
assertInstanceOf() |
判断对象是否为指定类的实例 | $this->assertInstanceOf(User::class, $user); |
注意:assertEquals 和 assertSame 的区别。前者用 == 比较,后者用 ===。比如 assertEquals(1, '1') 会通过,但 assertSame(1, '1') 会失败。我在项目中踩过这个坑——一个接口返回了字符串类型的数字,我用 assertEquals 测了没问题,上线后前端报类型错误。从那以后,我统一用 assertSame。
运行测试
写好了测试,怎么跑?三种方式:
1. 命令行直接跑
./vendor/bin/phpunit tests/UserServiceTest.php
跑单个文件,开发时最常用。
2. 跑整个 tests 目录
./vendor/bin/phpunit
不加参数,默认跑 tests/ 下所有测试。提交代码前记得跑一遍。
3. 过滤特定方法
./vendor/bin/phpunit --filter testCreateUser
只跑方法名包含 testCreateUser 的测试。调试时特别好用。
我个人习惯:在 IDE 里配置一个快捷键,一键运行当前文件。PhpStorm 里是 Ctrl+Shift+F10(Windows)或 Cmd+Shift+R(Mac)。写一行代码,按一下快捷键,看到绿色条,心里就踏实了。
第一个完整的测试示例
来,咱们写一个完整的。假设有个 Calculator 类:
// src/Calculator.php
class Calculator
{
public function add(int $a, int $b): int
{
return $a + $b;
}
}
对应的测试:
// tests/CalculatorTest.php
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
public function testAdd_WithPositiveNumbers_ReturnsSum()
{
$calculator = new Calculator();
$result = $calculator->add(2, 3);
$this->assertSame(5, $result);
}
public function testAdd_WithNegativeNumbers_ReturnsSum()
{
$calculator = new Calculator();
$result = $calculator->add(-1, -2);
$this->assertSame(-3, $result);
}
}
跑一下:
./vendor/bin/phpunit tests/CalculatorTest.php
PHPUnit 10.5.0 by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)
Time: 0.01 seconds, Memory: 6.00 MB
OK (2 tests, 2 assertions)
看到那两个点了吗?每个点代表一个通过的测试。如果失败会显示 F,并告诉你哪一行断言失败了。
核心要点:
- 测试类名 = 被测试类 + Test
- 测试方法名 = test + 方法名 + 场景 + 期望
- 断言用 assertSame 代替 assertEquals,更严格
- 命令行跑测试,看到绿色就对了
嗯,第一个测试就这么简单。别想得太复杂,测试说白了就是「写一段代码,验证另一段代码对不对」。你平时手动测的时候不也是输入几个值,看看结果对不对吗?现在只是把这个过程自动化了而已。
下一章咱们聊聊「测试替身」——当你的代码依赖数据库、API 或者文件系统时,怎么优雅地测试。