Infection 在 PHP 8.1 项目中用于暴露测试盲区与断言脆弱性,需使用 v5.4+、配置 phpVersion="8.1"、限定源码目录、排除枚举与测试文件、禁用无效变异器,并通过存活率分析驱动质量改进。

PHP 8.1 项目接入 Infection 做变异测试,核心不是“跑起来就行”,而是让变异结果真正驱动质量改进——它不替代单元测试,但能暴露测试覆盖的盲区、断言的脆弱性、以及逻辑分支的真实防御力。
安装与基础配置适配 PHP 8.1
Infection 5.x 起全面支持 PHP 8.1,需注意版本对齐:
- 使用 Composer 安装:composer require infection/infection --dev
- 确认最低要求:Infection v5.4+ 支持 PHP 8.1 的只读属性、枚举、交集类型等语法;低于此版本可能跳过含 enum 或 & 类型的文件
- 生成配置:vendor/bin/infection init,选择 PHPUnit 作为测试框架,并启用 --skip-prompt 快速生成 infection.json5
- 关键配置项中显式声明 PHP 版本:在 infection.json5 的 "phpVersion" 字段设为 "8.1"
精准限定变异范围,避免误伤与卡顿
盲目全量变异会拖慢 CI、淹没有效信号。应聚焦高风险/高变更区域:
- 在 infection.json5 中用 "source": { "directories": ["src/Domain", "src/Service"] } 锁定业务核心层,排除 DTO、迁移、模板等低逻辑密度目录
- 通过 "exclude": ["*Test.php", "Enum/*.php"] 排除测试类和枚举文件(枚举本身不可变,且其 case 值常被硬编码在 match 中,变异无意义)
- 禁用对 PHP 8.1 新语法的无效变异:在 "mutators" 下关闭如 "AssignAndBooleanOr"(PHP 8.1 短路优化后行为更严格)等易产生误报的规则
解读变异分数,定位真实薄弱点
存活率(Survived)高于 15% 通常意味着测试缺失或断言不足,需人工介入而非调高阈值:
立即学习“PHP免费学习笔记(深入)”;
- 关注“存活但应杀死”的典型场景:比如 match 表达式缺 case 分支,而测试只覆盖了 Active 和 Inactive,却没测 Pending —— Infection 会插入 Pending 变异体并存活,直接暴露穷尽性缺口
- 枚举状态流转逻辑(如 UserStatus::Active->Inactive)若未在测试中显式 assert 状态变更前后值,Infection 的 EnumValueMutator 会将 case Active = 'active' 变为 'pending' 并存活,提示你补全状态迁移断言
- 交集类型参数(如 LoggerInterface & ConfigurableInterface $service)若测试仅传入实现单个接口的 mock,Infection 的 TypeCoercionMutator 可能绕过类型检查并存活,倒逼你补全双重契约验证
集成进工程流程,形成闭环反馈
变异测试不应只在本地或 nightly 运行,而要嵌入关键质量关口:
- pre-push 钩子中加入:infection --min-msi=80 --min-covered-msi=90,MSI(Mutation Score Indicator)低于阈值则阻断推送
- CI 流水线中分两阶段:第一阶段运行常规 PHPUnit;第二阶段仅对新增/修改文件执行 infection --only-covered,节省时间且聚焦变更影响
- 将 infection.json5 提交至仓库,并在 README.md 添加「变异覆盖率 ≥ 85%」为质量红线,与 PHPStan level 6、PSR-12 格式化共同构成三重门禁



















