AI 生成单元测试能把覆盖率从 40% 拉到 80%,但覆盖率上去不等于缺陷被发现——模型优化的目标是”测试跑绿”,不是”测试有效”。想让 AI 写的测试真有价值,做法是基于需求描述生成、按分支清单下指令、并对断言做逐条审查,三件事缺一件,你得到的就是一堆永远通过的空测试。
为什么 AI 写的测试”绿得发慌”
GitHub 官方博客在讲 Copilot 生成单元测试时反复强调一点:写测试之前要先想清楚这个测试的用途和读者是谁——是要支撑重构、还是给新人当文档、还是要满足验收。没有这个前提,再多的测试也只是凑数。
实践中 AI 生成测试的四个典型问题:
- 幻觉断言:断言写成了函数根本不会返回的类型,比如登录成功断言
result == True,实际返回的是 token 对象。 - 虚假覆盖率:只断言
list.size() > 0这种恒真条件,价格计算、库存校验、并发这些真正的风险点一个没碰。 - 过度 mock:把真正含有业务逻辑的依赖 mock 掉了,测试跑的是 mock 而不是代码。
- 照着实现写测试:代码里本来就有 bug,测试”正确地”断言了这个错误输出,等于把 bug 固化成契约。
先分清楚三种测试,别让 AI 全包
| 类型 | 适合 AI 生成吗 | 原因 |
|---|---|---|
| 纯函数单元测试 | 非常适合 | 范围小、真值容易靠执行验证 |
| 边界与异常用例 | 适合(需下指令) | 模型擅长枚举空值、越界、负数、 Unicode |
| 集成 / 并发 / 性能测试 | 不建议 | 需要真实数据库、容器、时序,AI 只会产出”看起来合理”的跳过版本 |
结论很直接:让 AI 做它能被验证的那一层。集成测试和并发测试自己写,或者至少逐行审。
四步落地法
- 写输入说明:先把函数的需求喂给 AI(接口文档、验收标准、 PRD 描述),而不是只喂实现代码。从实现反推生成的测试会把 bug 一起固化。
- 给出分支清单:明确列出你关心的分支——0 值、边界值、非法入参、空集合、并发写、超时。让模型”按这些分支各写一条”,而不是”写点测试”。
- 要求失败用例:追加一句”每条测试必须在这个逻辑被改错时失败”。这一句能把模型从”跑通”切换到”验证”,是质量分水岭。
- 人工审断言:只看断言,不看结构。逐条问自己:如果实现错了,这条断言会红吗?会,留下;不会,删掉重写。
可直接复制的提示词
为下面的函数生成单元测试。
需求描述:<粘贴接口文档或验收标准>
必须覆盖的分支:入参为 0 、入参为负数、超过上限、空集合、 null 、并发写入同一 key 。
要求:
1. 每个分支一条独立测试,互不依赖;
2. 断言必须检查业务结果,不允许只判断"不为 null"或"没抛异常";
3. 每条测试在实现被改错时必须失败,做不到就说明原因;
4. 不要 mock 掉包含核心逻辑的依赖。
一个折扣计算的对比例子
朴素版本:base=100, discount=10% → 90,只有一条,跑通即绿,什么都证明不了。
按上面的提示词生成出来的是另一批:折扣为 0% 时返回原价;折扣为 100% 时返回 0 而不是负数;折扣超过 100% 时的处理策略(拒绝还是允许负数,测试会逼你做出决定);负原价应报错;会员折扣与折扣的叠加顺序是否符合业务规则;金额落在 19.995 这种分位边界时是向上、向下还是四舍六入五成双。
差别在于:后者会暴露需求里的模糊地带,前者只会让报告好看。
三个必须人工把关的地方
- 依赖真实数据库的测试:AI 会写看起来对但悄悄跳过关键步骤的版本。
- 时间、随机数、并发相关的测试:不确定性的输入 AI 看不见,断言往往凭空假设。
- 快照测试(snapshot):AI 很喜欢生成,但它只是把当前输出拍平存下来,改动即通过,几乎没有回归价值,建议少用。
团队协作上的建议
把上面四步写进项目规则文件,让每个成员调用 AI 时都用同一套指令,产出质量才稳定。测试生成完记得走一遍AI 代码审查工作流,把”AI 写测试、 AI 审测试、人做判断”这条线跑顺;补测试的场景也可以结合GitHub Copilot 免费额度的用法,把额度用在刀刃上。另外,Cline 这类能自己跑测试并迭代的插件在整包补测试时效率最高,因为它能根据红色失败反复修。









评论 (0)