PHP中的突变测试:杀死测试,让它们真正工作

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

你的测试是安全的假象吗?



想象一下:你的代码覆盖率达到95%,所有测试都是绿色的,CI/CD顺利通过。你确信你的PHP代码已经免受回归问题的困扰。但事实真的如此吗?



我自己很长一段时间都活在这种假象中,直到我遇到一个情况:测试通过了,尽管我无意中将关键条件中的 && 替换成了 ||。测试根本没有检查这个分支。覆盖率是100%,但逻辑却不是。



认识一下:突变测试 (mutation testing) —— 一种无情地“杀死”你的测试,以查明它们实际可靠程度的方法。在本文中,我们将探讨如何使用强大的工具 Infection 在PHP中应用它,以及为什么这会改变游戏规则。



什么是突变测试,为什么需要它?



突变测试是一种方法,它会向你的源代码中引入微小的、有意的更改(突变)。例如,将运算符 + 改为 -,将 true 改为 false,或者删除一整行代码。每次突变后,都会运行你的测试。



如果测试失败 —— 突变被“杀死”,意味着测试确实检查了这段代码。如果测试通过 —— 突变“存活”了。这是一个危险信号:要么测试没有检查这个条件,要么测试编写有误。



与“代码覆盖率”指标不同,后者仅显示哪些代码行被执行,突变测试检查的是检查的质量。高覆盖率并不能保证什么,而突变得分指标 (MSI) 才是可靠性的真实指标。



为什么这对PHP开发者很重要?

  • 发现“无效”测试 —— 那些总是绿色但什么也不检查的测试。
  • 识别逻辑中的空白 —— 例如,遗漏的边界条件。
  • 提高重构时的信心 —— 你确切地知道哪些测试在保护代码。
  • 节省时间 —— 无需手动审查测试,即可获得自动化报告。


PHP中的突变测试工具



PHP领域中的领导者是 Infection(以前称为Humbug)。它可以轻松与PHPUnit和Pest集成,支持多种突变,并提供清晰的报告。



其他选项包括:Humbug(前身,但不太活跃)和 Mutagen(实验性)。我们将重点介绍Infection——它是现代标准。



实践:在项目中配置Infection



让我们安装Infection并在一个真实示例上运行。假设我们有一个用于计算折扣的简单类:



<?php// src/DiscountCalculator.phpclass DiscountCalculator{    public function calculate(float $price, bool $isPremium): float    {        if ($isPremium) {            return $price * 0.9; // 10%折扣        }

return $price; }}


以及它的测试:



<?php// tests/DiscountCalculatorTest.phpuse PHPUnit\\Framework\\TestCase;

class DiscountCalculatorTest extends TestCase{ public function testPremiumDiscount(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(100.0, true); $this->assertEquals(90.0, $result); }

public function testRegularPrice(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(100.0, false); $this->assertEquals(100.0, $result); }}


覆盖率为100%。但让我们用突变来检查一下。



安装并运行Infection



composer require --dev infection/infection./vendor/bin/infection


之后

博客

书籍推荐