首页 / PHP 入门教程 / PHP 单元测试基础

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);
}
Note

PHP 8.1 起,setAccessible(true) 不再是必须的,反射方法默认就能访问私有成员。保留它也不会报错,只是为了兼容旧版本。过度测试私有方法会增加维护成本,优先通过公共接口验证行为。


小结

PHPUnit 是 PHP 单元测试的标准工具。从 assertEquals 开始,逐步掌握异常测试和数据提供者,让测试成为开发流程的一部分。


来源:参考了 php-the-right-way「Testing」、PHPUnit 官方文档,改写后所得。