本文目录导读:

在 PHP 中给代码加测试,最主流的方式是使用 PHPUnit,以下是完整的实践指南:
安装 PHPUnit
使用 Composer 安装(推荐)
# 全局安装 composer global require phpunit/phpunit # 或项目内安装(开发环境) composer require --dev phpunit/phpunit
基础测试示例
待测试的类文件 Calculator.php
<?php
class Calculator {
public function add($a, $b) {
return $a + $b;
}
public function divide($a, $b) {
if ($b === 0) {
throw new InvalidArgumentException('Division by zero');
}
return $a / $b;
}
}
对应的测试文件 CalculatorTest.php
<?php
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase {
private $calculator;
// 每个测试方法执行前运行
protected function setUp(): void {
$this->calculator = new Calculator();
}
// 测试加法
public function testAdd() {
$result = $this->calculator->add(2, 3);
$this->assertEquals(5, $result);
}
// 测试除法正常情况
public function testDivide() {
$result = $this->calculator->divide(10, 2);
$this->assertEquals(5, $result);
}
// 测试除零异常
public function testDivideByZero() {
$this->expectException(InvalidArgumentException::class);
$this->calculator->divide(10, 0);
}
}
运行测试
# 运行单个测试文件 vendor/bin/phpunit tests/CalculatorTest.php # 运行目录下所有测试 vendor/bin/phpunit tests/ # 运行特定方法 vendor/bin/phpunit --filter testAdd tests/CalculatorTest.php # 输出详细信息 vendor/bin/phpunit --testdox tests/
常用断言方法
// 数值断言
$this->assertEquals(4, $result); // 值相等
$this->assertSame(4, $result); // 值和类型都相等
$this->assertGreaterThan(3, $result); // 大于
$this->assertLessThan(5, $result); // 小于
// 布尔断言
$this->assertTrue($condition);
$this->assertFalse($condition);
// 数组断言
$this->assertCount(3, $array);
$this->assertContains('value', $array);
$this->assertArrayHasKey('key', $array);
// 对象断言
$this->assertInstanceOf(ClassName::class, $object);
$this->assertNull($object);
$this->assertNotNull($object);
// 字符串断言
$this->assertStringContainsString('substring', $string);
$this->assertMatchesRegularExpression('/pattern/', $string);
数据提供器(Data Providers)
class CalculatorTest extends TestCase {
/**
* @dataProvider additionProvider
*/
public function testAdd($a, $b, $expected) {
$calculator = new Calculator();
$this->assertEquals($expected, $calculator->add($a, $b));
}
public function additionProvider() {
return [
'positive numbers' => [1, 2, 3],
'zero' => [0, 0, 0],
'negative numbers' => [-1, -2, -3],
'decimals' => [1.5, 2.5, 4.0],
];
}
}
测试异常
class UserServiceTest extends TestCase {
public function testInvalidEmail() {
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid email format');
$userService = new UserService();
$userService->createUser('invalid-email');
}
public function testDatabaseError() {
$mockDb = $this->createMock(PDO::class);
$mockDb->method('query')
->will($this->throwException(new PDOException()));
$this->expectException(PDOException::class);
// 测试代码...
}
}
模拟对象(Mocking)
use PHPUnit\Framework\TestCase;
class UserControllerTest extends TestCase {
public function testGetUser() {
// 创建模拟对象
$userRepository = $this->createMock(UserRepository::class);
// 配置模拟行为
$userRepository->expects($this->once())
->method('findById')
->with(1)
->willReturn(new User(['id' => 1, 'name' => 'John']));
// 注入模拟对象
$controller = new UserController($userRepository);
$result = $controller->getUser('1');
$this->assertEquals('John', $result['name']);
}
}
清理数据库测试数据
class UserRepositoryTest extends TestCase {
private $db;
protected function setUp(): void {
$this->db = new PDO('sqlite::memory:');
$this->db->exec('CREATE TABLE users (id INT, name TEXT)');
}
protected function tearDown(): void {
$this->db->exec('DROP TABLE users');
}
public function testUserInsert() {
$this->db->exec("INSERT INTO users VALUES (1, 'John')");
$result = $this->db->query("SELECT * FROM users WHERE id=1");
$this->assertEquals('John', $result->fetch()['name']);
}
}
phpunit.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
colors="true"
stopOnFailure="false">
<!-- 测试套件路径 -->
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
<!-- 代码覆盖率 -->
<coverage>
<include>
<directory>./src</directory>
</include>
</coverage>
</phpunit>
最佳实践建议
- 测试命名规则:测试文件以
Test.php方法以test开头 - 一个方法只测一件事:保持测试单一职责
- 使用数据提供器:减少重复测试代码
- 测试真实场景:不要过度使用 mock,重要的逻辑要用真实对象
- 运行所有测试:CI/CD 里配置自动运行测试
- 代码覆盖率:定期检查覆盖率指标
# 生成代码覆盖率报告 vendor/bin/phpunit --coverage-html build/coverage
这样可以直观地看到哪些代码没有测试覆盖。
其他测试框架
- PHPSpec:行为驱动开发(BDD)风格
- Codeception:功能测试和验收测试
- Pest:简洁优雅的测试框架
推荐先学习 PHPUnit,这是最主流的选择,然后根据需求学习其他框架。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播