PHP 入门教程
PHP 单元测试基础
本教程共 65 篇 · 第 60 篇 · 更新于 2026-07-24 · 约 9 分钟阅读
PHPPHP8PHPUnit单元测试TDD测试用例断言
60. PHP 单元测试基础
本节目标:理解单元测试的价值,掌握 PHPUnit 的安装和基本用法,能够编写简单的测试用例。
手动刷新浏览器验证代码,效率低且容易遗漏。单元测试用代码自动验证代码,是保障项目质量的重要手段。
1. 为什么需要单元测试
- 快速验证:修改代码后立即知道是否破坏了现有功能
- 安全重构:有测试覆盖才敢大胆优化代码结构
- 文档作用:测试用例展示了函数的预期用法和边界条件
- 持续集成:配合 CI/CD 自动拦截有问题的代码
2. 安装 PHPUnit
通过 Composer 安装:
composer require --dev phpunit/phpunit
创建配置文件 phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Application Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
3. 第一个测试用例
假设有一个计算类:
<?php
// src/Calculator.php
class Calculator
{
public function add(float $a, float $b): float
{
return $a + $b;
}
public function divide(float $a, float $b): float
{
if ($b == 0) {
throw new InvalidArgumentException('除数不能为0');
}
return $a / $b;
}
}
编写测试:
<?php
// tests/CalculatorTest.php
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
public function testAdd(): void
{
$calc = new Calculator();
$this->assertEquals(5, $calc->add(2, 3));
$this->assertEquals(0, $calc->add(-1, 1));
}
public function testDivide(): void
{
$calc = new Calculator();
$this->assertEquals(2, $calc->divide(6, 3));
}
public function testDivideByZeroThrowsException(): void
{
$this->expectException(InvalidArgumentException::class);
$calc = new Calculator();
$calc->divide(10, 0);
}
}
运行测试:
vendor/bin/phpunit
4. 常用断言方法
| 断言 | 作用 |
|---|---|
assertEquals(期望, 实际) | 两个值相等 |
assertSame(期望, 实际) | 两个值全等(类型和值都相同) |
assertTrue(表达式) | 表达式为真 |
assertFalse(表达式) | 表达式为假 |
assertNull(变量) | 变量为 null |
assertCount(数量, 数组) | 数组元素个数匹配 |
assertInstanceOf(类名, 对象) | 对象是某类的实例 |
expectException(类名) | 预期抛出某异常 |
5. 数据提供者
同一测试逻辑,多组输入数据,可用数据提供者:
<?php
class CalculatorTest extends TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAddWithDataProvider(float $a, float $b, float $expected): void
{
$calc = new Calculator();
$this->assertEquals($expected, $calc->add($a, $b));
}
public static function additionProvider(): array
{
return [
'正数相加' => [2, 3, 5],
'零加正数' => [0, 5, 5],
'负数相加' => [-1, -2, -3],
'小数相加' => [1.5, 2.5, 4.0],
];
}
}
Tip数据提供者让测试用例更清晰,每组数据都有独立名称,失败时容易定位。
6. 测试私有方法
测试通常只关注公共接口。如果必须测试私有逻辑,可通过反射:
<?php
public function testPrivateMethod(): void
{
$obj = new MyClass();
$method = new ReflectionMethod(MyClass::class, 'privateHelper');
// PHP 8.1+ 无需 setAccessible,反射可直接访问私有方法
$method->setAccessible(true);
$result = $method->invoke($obj, '参数');
$this->assertEquals('预期结果', $result);
}
NotePHP 8.1 起,
setAccessible(true)不再是必须的,反射方法默认就能访问私有成员。保留它也不会报错,只是为了兼容旧版本。过度测试私有方法会增加维护成本,优先通过公共接口验证行为。
小结
PHPUnit 是 PHP 单元测试的标准工具。从 assertEquals 开始,逐步掌握异常测试和数据提供者,让测试成为开发流程的一部分。
来源:参考了 php-the-right-way「Testing」、PHPUnit 官方文档,改写后所得。