AI 生成补丁的变异测试:证明测试能杀死错误而非只跑绿
行覆盖率无法证明测试会拒绝错误补丁。本文把变异测试接入 AI 改动门禁,用限定范围、幸存变异审查和基线差分验证测试是否真正约束了新行为。
本文要点
- 主题聚焦:AI Agent、TypeScript、DevOps
- 适合人群:独立开发者、全栈工程师、AI 应用开发者
- 核心价值:快速理解背景、实践路径、常见误区和工程建议
AI 能在几秒内同时生成实现和测试,这也带来一个隐蔽问题:测试可能只是复述实现。它执行了新增分支,行覆盖率达到 100%,但把 > 改成 >=、删除鉴权条件或颠倒布尔值后仍然通过。变异测试主动制造这些小错误,再检查测试能否将它们“杀死”,因而回答的是更重要的问题:这组断言是否真的限制了补丁允许的行为。
它不是普通覆盖率的替代品,也不应对整个仓库盲跑。编程 Agent 的门禁要将变异范围绑定到本次 diff、风险声明和批准过的测试计划。通用的静态检查与回归层仍由编程 Agent 的改动验证门负责;变异层只对关键逻辑提供反事实证据。
冻结输入后再比较基线
一次可复现运行至少固定提交 SHA、Node 与包管理器版本、锁文件哈希、测试命令、变异器版本和配置哈希。以 Node 22.18.0、pnpm 10.14.0 的仓库为例,CI 先从干净检出执行:
node --version
pnpm --version
sha256sum pnpm-lock.yaml stryker.conf.json
pnpm install --frozen-lockfile
pnpm exec stryker --version
pnpm exec stryker run stryker.conf.json
变异器依赖应在 package.json 中用精确版本并进入锁文件,不能在 CI 临时下载 latest。报告保存 baseSha、headSha、选中的源码文件、测试集合、超时、并发数和每个 mutant 的位置。只有这些输入一致,基线分数与补丁分数才可比较。
范围由 git diff --unified=0 BASE...HEAD 产生,但不能只变异新增行。若 Agent 修改了价格计算函数中的一个条件,至少要覆盖该函数以及它直接影响的校验器;若改了公共类型,则扩大到相关实现。纯格式、生成文件和无法直接执行的类型声明可排除,但排除项必须写进报告。仓库结构和依赖边界可先由编程 Agent 仓库地图确定。
不要只看一个 mutation score
变异结果至少分为 killed、survived、no coverage、timeout 和 compile error。门禁采用分层规则,而不是“总分超过 80%”这一条:
| 范围 | 合并条件 |
|---|---|
| 新增或修改的业务分支 | survived = 0,no coverage = 0 |
| 鉴权、金额、删除、迁移保护条件 | 所有可执行 mutant 必须被杀死 |
| 相邻未修改代码 | mutation score 较冻结基线下降不超过 2 个百分点,且无新增高风险幸存项 |
| timeout / compile error | 必须分类,不能自动计为 killed |
例如 if (actor.id !== ownerId) deny() 被删除后测试仍绿,这不是“分数略低”,而是安全门直接失败。相反,日志文本中一个等价字符串变异幸存,可以由 reviewer 标记为等价或低价值,但必须附源码位置、理由和批准人,不能让 Agent 自己把它加入忽略列表。
幸存变异驱动测试修复
修复顺序不是为每个 mutant 添加一个脆弱断言。先把幸存项归为缺失测试、等价变异、不可观测行为或测试隔离问题。缺失测试应补充业务可观察结果,例如状态、返回值、持久化和副作用,而不是断言内部函数被调用几次。需要扩大输入空间时,可结合AI 测试生成,但生成的案例仍要由需求不变量解释。
每次修复后重跑同一个 frozen mutant set;如果源码又被改动,则旧报告失效并重新生成集合。最多允许两轮 Agent 自动修复,仍有高风险幸存项就转人工审阅。禁止删除断言、扩大 mutate.exclude、增加全局超时或把失败测试改成跳过,除非验证计划明确记录差异。
控制成本与误报
PR 阶段只跑受影响模块,夜间任务对全仓库轮转;合并前对安全和财务目录强制完整变异。缓存只能复用基线提交的编译产物,不能把另一个 diff 的 mutant 结果当成当前证据。若运行时间超过 12 分钟,门禁应报告“预算耗尽”并安排受控的完整 CI,而不是把未执行项算成通过。
先在已知错误样本上校准配置:准备越界、空值、权限反转和错误回滚四类补丁,确认变异器能生成相关 mutant,测试会失败。若关键错误无法被表达,就增加人工故障注入或专项测试,而不是宣传变异分数。完整流水线的证据留存与重跑策略可参考CI/CD 流水线设计。
最终产物应包含机器可读报告、幸存项清单、等价项审批、命令与版本、耗时以及回滚判断。变异测试的价值不是制造一个更漂亮的百分比,而是让 reviewer 看见:AI 写的测试面对“几乎正确但实际错误”的实现时,确实会红。
Related