Infection 变异分数计算
解读
在国内 PHP 技术面试中,单元测试覆盖率已逐渐成为“标配”指标,但“覆盖率够了,Bug 还是很多”是面试官最爱追问的痛点。Infection 作为 PHP 生态唯一成熟、落地案例多的“变异测试(Mutation Testing)”工具,通过故意植入“变异算子”(如把 == 改成 !=、把 ++$i 改成 --$i 等),检验测试用例能否“杀死”这些变异体,从而量化测试的“有效性”。
“变异分数”是 Infection 最核心的输出指标,直接决定测试用例是否真正值得信赖。面试官问“怎么算”,不仅是考察公式记忆,更是考察你对指标背后“成本—收益”的理解、对工程化落地的权衡,以及能否把结论翻译成团队能执行的动作(例如 CI 门禁、增量 MR 策略、性能调优等)。回答时务必把“公式 → 参数 → 调优 → 门禁”讲全,才能体现资深后端工程师的闭环思维。
知识点
- 变异测试基础概念:变异体(Mutant)、杀死(Killed)、存活(Escaped)、等价(Equivalent)、超时(Timeout)。
- Infection 的三种运行模式:常规模式(默认)、仅覆盖模式(
--only-covered)、最小变异集模式(--min-msi配合--filter)。 - 指标公式:
MSI(Mutation Score Indicator) = (Killed + Timeout + Timed Out) / (Total Mutants − Equivalent) × 100%
Covered Code MSI = (Killed + Timeout) / (Covered Mutants − Equivalent) × 100% - 国内落地常见阈值:
新服务 MSI ≥ 60% 可进主干,老服务渐进式提升到 45%;
增量文件要求 Covered MSI ≥ 80%,防止“破窗”。 - 性能调优手段:
使用paratest做多进程执行、开启opcache.enable_cli=1、把memory_limit调到 512M 以上;
等价变异体自动检测(--min-msi配合roave/infection-static-analysis-plugin)减少误报。 - CI 集成要点:
在 GitLab-CI 中把 Infection 跑在test:mutation阶段,产物infection.log与junit.xml一并归档;
合并请求评论机器人读取infection.json的msi字段,低于阈值自动 block。 - 与业务指标挂钩:
把“线上缺陷密度”与“MSI 趋势”做双轴图,每月复盘,证明变异测试对缺陷率有显著下降(国内甲方最认这种量化汇报)。
答案
变异分数(MSI)由 Infection 在 infection.json 中自动输出,核心公式:
MSI = (被杀死的变异体数 + 超时变异体数) ÷ (总变异体数 − 等价变异体数) × 100%
示例:
某支付模块共生成 2 000 个变异体,其中 160 个被判定为等价,运行后 1 280 个被杀死、80 个超时。
MSI = (1280 + 80) ÷ (2000 − 160) × 100% = 1360 ÷ 1840 × 100% ≈ 73.9%
国内工程实践:
- 先在
phpunit.xml中开启<coverage><include><directory suffix=".php">src</directory></include></coverage>,保证覆盖率数据完整; - 运行
infection --only-covered --threads=8 --min-msi=60,把 MSI 低于 60% 的 MR 直接拒绝; - 对历史大仓库采用“增量模式”:
infection --git-diff-lines=origin/main --ignore-msi-with-no-mutations,只检测变更行,5 分钟内跑完,解决“全量跑太久”的痛点; - 把 MSI 趋势接入 Prometheus,通过 Grafana 面板每周邮件提醒,形成“测试有效性”可视化,方便技术总监在季度汇报时展示“质量内建”成果。
拓展思考
- 等价变异体识别一直是变异测试的“阿喀琉斯之踵”。PHP 社区正在尝试结合 Psalm、PHPStan 的静态分析,自动过滤“不可达”变异体;你可以调研
roave/infection-static-analysis-plugin,并给出落地 PR 案例。 - 当 MSI 已达标但线上仍出 Bug,往往是“业务语义”层面缺失。可引入“属性级变异”(如把订单状态常量
STATUS_PAID改成STATUS_CANCELLED),让变异体更贴近真实业务错误,考验你对“业务规则测试”的理解。 - 大型 SaaS 场景下,微服务数量多、全量跑 Infection 成本高。可设计“分层门禁”:
单元层 MSI ≥ 70% → 集成层变异(契约测试层)≥ 50% → 端到端变异(UI 自动化)≥ 30%,形成“金字塔”有效性模型,既保证质量又控制 CI 预算。