本文目录导读:

在 PHP 中进行变异测试,主要是通过引入变异测试工具,在代码中注入缺陷(变异体),然后运行测试套件来检测现有测试是否能够发现这些变异,如果测试未能发现某个变异,说明该变异的对应代码段缺乏足够的测试覆盖。
以下是 PHP 变异测试的完整指南:
主要的变异测试工具
Infection(最流行)
Infection 是目前 PHP 生态中最成熟、最活跃的变异测试框架。
Humbug
Humbug 是较早的变异测试工具,但已不再维护,现在推荐使用 Infection。
安装与配置 Infection
安装
使用 Composer 安装:
composer require --dev infection/infection
基本配置
创建 infection.json 配置文件:
{
"$schema": "https://raw.githubusercontent.com/infection/infection/master/resources/schema.json",
"source": {
"directories": [
"src"
]
},
"timeout": 10,
"logs": {
"text": "infection.log"
},
"mutators": {
"global-ignores": [
"src/Adapters/"
]
}
}
或者使用命令行直接指定源目录:
vendor/bin/infection --source=src --test-framework=phpunit --covered-only
运行变异测试
基本运行
vendor/bin/infection
高级运行选项
# 仅测试已覆盖的代码(更快) vendor/bin/infection --covered-only # 指定测试框架(PHPUnit 或 PHPSpec) vendor/bin/infection --test-framework=phpunit # 限制变异数量(加速测试) vendor/bin/infection --max-mutations=100 # 跳过未覆盖代码 vendor/bin/infection --skip-covered
理解变异测试结果
运行后会生成类似以下的输出:
Processing source code files: 50
Processing test classes: 100
...
2 mutations were generated:
1) /path/to/file.php:76 [M] PublicVisibility
--- Original
+++ New
@@ @@
- public function calc()
+ protected function calc()
Mutation was not detected by tests
结果类型
- Killed:测试发现了变异,说明该代码被充分测试
- Escaped:测试未发现变异,需要增加测试
- Uncovered:变异代码从未被执行,需要添加测试
- Timeout:测试运行超时
变异测试指标
变异测试的核心指标是 MSI(Mutation Score Indicator):
MSI = (Killed Mutants / Total Mutants) × 100
目标:通常建议 MSI 达到 80% 以上。
在 CI/CD 中集成
在 GitLab CI 或 GitHub Actions 中:
# GitHub Actions 示例
name: Mutation Testing
on: [push]
jobs:
mutation-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- run: composer install
- run: vendor/bin/infection --min-msi=80 --covered-only
env:
CI: true
实用技巧
忽略不可测试的代码
{
"source": {
"directories": [
"src"
],
"exclude": [
"src/Config",
"src/Models/Entity"
]
},
"mutators": {
"global-ignores": [
"src/Kernel.php",
"src/Doctrine/"]
}
}
只测试特定类
# 只测试 User 类的变异 vendor/bin/infection --filter=User
提高运行速度
- 使用
--threads=4并行执行 - 使用
--covered-only只变异已覆盖代码 - 限制最大变异数:
--max-mutations=500
与 PHPUnit 协作
确保 PHPUnit 测试快速执行,可以设置 --coverage:
# 生成覆盖率并只测试剩余代码 vendor/bin/infection --coverage=coverage --min-msi=85
完整配置文件示例
{
"$schema": "https://raw.githubusercontent.com/infection/infection/master/resources/schema.json",
"source": {
"directories": ["src/"]
},
"logs": {
"text": "reports/infection.txt",
"html": "reports/infection.html",
"github": "true"
},
"mutators": {
"global-ignores": [
"src/Entity/*",
"src/DTO/*"
],
"@default": true,
"CastInt": false,
"DecrementInteger": false
},
"min-msi": 85,
"min-covered-msi": 90,
"threads": 4,
"timeout": 10,
"executableFinder": {
"phpunit": "vendor/bin/phpunit"
}
}
常见问题与解决
| 问题 | 解决方案 |
|---|---|
| 测试太慢 | 增加 --threads,使用 --covered-only |
| 变异逃脱太多 | 审查被漏掉的测试,增加边界条件测试 |
| 误报变异 | 使用 global-ignores 忽略特定代码 |
| CI 内存不足 | 设置 MEMORY_LIMIT=-1 或增加 PHP 内存限制 |
| 覆盖率高但 MSI 低 | 检查测试断言是否过于宽泛 |
推荐工作流程
# 1. 首先运行正常测试确保通过 composer test # 2. 生成覆盖率报告 vendor/bin/phpunit --coverage-xml=coverage/coverage-xml # 3. 运行变异测试 vendor/bin/infection --coverage=coverage --min-msi=85 # 4. 查看报告并补充测试 open reports/infection.html
变异测试是提升测试质量的重要手段,通过 Infection,你可以:
- 准确衡量测试的有效性
- 发现测试盲区
- 不断提高 MSI 直至达到理想水平(80%+)
- 防止回归测试不充分的问题
建议先从关键业务逻辑代码开始,逐步推广到全项目,因为变异测试运行时间较长(可能是普通测试的 10-20 倍),需要对速度和覆盖进行平衡。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播