PHP 如何写单元测试
写单元测试这件事,对很多刚接触PHP的开发者来说,总觉得是“写代码之外的额外工作”,要么嫌麻烦,要么不知道从哪下手。其实单元测试说白了,就是给你写的每一小段代码做“体检”——就像你买水果前要挑挑有没有坏的,写好的函数、类方法,也得确认它在各种情况下都能正常干活。今天就用生活化的例子,一步步讲清楚PHP怎么写单元测试。
先搞懂:单元测试到底测什么?
举个简单例子:你写了一个计算外卖配送费的函数,规则是“订单满30免配送费,不满的话距离1公里内收5元,超1公里每多1公里加2元”。这个函数里,满30的情况、不满但距离近的情况、距离远的情况,都是你要测的“单元”——每个独立的小逻辑。

单元测试的核心就是:把每个小逻辑单独拆出来,模拟它可能遇到的各种情况,看看结果是不是和你预期的一样。
第一步:准备工具——用最常用的 PHPUnit
写PHP单元测试,最主流的工具是PHPUnit,就像你要体检得先拿体检表,它就是那个“测试工具包”。安装也简单:如果你的项目用Composer管理依赖,只要在命令行输一句 composer require --dev phpunit/phpunit,就装好了,而且只会在开发环境用,不会影响上线的代码。
装完后,你可以在项目根目录建一个 tests 文件夹,专门放测试文件,就像体检报告都放一个文件夹里,好找。
第二步:写第一个简单测试——测刚才的配送费函数
假设你有个项目,写了一个叫 Delivery 的类,里面有个 calculateFee 方法,就是算配送费的。现在要给这个方法写测试:
- 先在
tests文件夹里建一个测试文件,名字要和要测的类对应,比如测Delivery类,测试文件就叫DeliveryTest.php——PHP习惯用“类名+Test”的命名,方便识别。 - 测试文件里要继承PHPUnit提供的基础测试类
PHPUnit\Framework\TestCase,就像体检要去专门的体检机构,继承这个类才会有测试需要的方法。 - 写测试方法:方法名要以
test开头,比如testFullOrderFreeDelivery,意思是“测满30免配送费的情况”。
举个具体的测试代码:
`php
use PHPUnit\Framework\TestCase;
use App\Delivery; // 这里是你项目里的Delivery类路径
class DeliveryTest extends TestCase
{
// 测试订单满30,应该免配送费
public function testFullOrderFreeDelivery()
{
$delivery = new Delivery();
$result = $delivery->calculateFee(40, 0.8); // 订单40元,距离0.8公里
// 断言结果是0,也就是预期值
$this->assertEquals(0, $result);
}
// 测试订单不满30,距离1公里内,收5元
public function testShortDistanceFee()
{
$delivery = new Delivery();
$result = $delivery->calculateFee(25, 0.9); // 订单25元,距离0.9公里
$this->assertEquals(5, $result);
}
// 测试订单不满30,距离超1公里,算加价
public function testLongDistanceFee()
{
$delivery = new Delivery();
$result = $delivery->calculateFee(25, 2); // 订单25元,距离2公里
// 1公里内5元,超了1公里(2-1=1)加2元,总共7元
$this->assertEquals(7, $result);
}
}
`
这里的 assertEquals 就是测试的“判断标准”——你预期结果是多少,就用这个方法和实际运行的结果比,不一样的话,PHPUnit就会告诉你哪里错了。
第三步:运行测试,看结果
写好测试后,在命令行里输入 vendor/bin/phpunit tests/DeliveryTest.php,PHPUnit就会自动跑你写的几个测试方法。如果所有都显示“OK”,说明你的函数在这些场景下没问题;要是有失败,比如刚才的配送费算成了6元,它会直接告诉你哪个方法、哪行代码出了问题,省得你手动一个个试。
小技巧:别漏了“边界情况”
刚才的例子里,除了普通情况,还要想想边界——比如订单刚好30元,距离刚好1公里,这些容易忽略的点。比如再加个测试:testExactly30Order,测订单刚好30元,是不是也能免配送费,别因为少写了个等于号就出错。
说白了,PHP写单元测试没那么复杂,核心就是“找个工具,把每个小函数的各种情况用代码写出来核对”——就像你给自行车打气,要检查气门芯、车胎、气筒接口,一个个确认,才敢骑。习惯了之后,不仅能减少上线后的bug,改代码的时候也更放心,不用怕改了这里影响了那里。