跳到主内容

AI 生成单元测试:覆盖率上去了,为什么还是抓不到 bug

100%
AI 生成单元测试:覆盖率上去了,为什么还是抓不到 bug

AI 生成单元测试能把覆盖率从 40% 拉到 80%,但覆盖率上去不等于缺陷被发现——模型优化的目标是”测试跑绿”,不是”测试有效”。想让 AI 写的测试真有价值,做法是基于需求描述生成、按分支清单下指令、并对断言做逐条审查,三件事缺一件,你得到的就是一堆永远通过的空测试。

为什么 AI 写的测试”绿得发慌”

GitHub 官方博客在讲 Copilot 生成单元测试时反复强调一点:写测试之前要先想清楚这个测试的用途和读者是谁——是要支撑重构、还是给新人当文档、还是要满足验收。没有这个前提,再多的测试也只是凑数。

实践中 AI 生成测试的四个典型问题:

  • 幻觉断言:断言写成了函数根本不会返回的类型,比如登录成功断言 result == True,实际返回的是 token 对象。
  • 虚假覆盖率:只断言 list.size() > 0 这种恒真条件,价格计算、库存校验、并发这些真正的风险点一个没碰。
  • 过度 mock:把真正含有业务逻辑的依赖 mock 掉了,测试跑的是 mock 而不是代码。
  • 照着实现写测试:代码里本来就有 bug,测试”正确地”断言了这个错误输出,等于把 bug 固化成契约。

先分清楚三种测试,别让 AI 全包

类型适合 AI 生成吗原因
纯函数单元测试非常适合范围小、真值容易靠执行验证
边界与异常用例适合(需下指令)模型擅长枚举空值、越界、负数、 Unicode
集成 / 并发 / 性能测试不建议需要真实数据库、容器、时序,AI 只会产出”看起来合理”的跳过版本

结论很直接:让 AI 做它能被验证的那一层。集成测试和并发测试自己写,或者至少逐行审。

四步落地法


  1. 写输入说明:先把函数的需求喂给 AI(接口文档、验收标准、 PRD 描述),而不是只喂实现代码。从实现反推生成的测试会把 bug 一起固化。

  2. 给出分支清单:明确列出你关心的分支——0 值、边界值、非法入参、空集合、并发写、超时。让模型”按这些分支各写一条”,而不是”写点测试”。

  3. 要求失败用例:追加一句”每条测试必须在这个逻辑被改错时失败”。这一句能把模型从”跑通”切换到”验证”,是质量分水岭。

  4. 人工审断言:只看断言,不看结构。逐条问自己:如果实现错了,这条断言会红吗?会,留下;不会,删掉重写。

可直接复制的提示词

为下面的函数生成单元测试。
需求描述:<粘贴接口文档或验收标准>
必须覆盖的分支:入参为 0 、入参为负数、超过上限、空集合、 null 、并发写入同一 key 。
要求:
1. 每个分支一条独立测试,互不依赖;
2. 断言必须检查业务结果,不允许只判断"不为 null"或"没抛异常";
3. 每条测试在实现被改错时必须失败,做不到就说明原因;
4. 不要 mock 掉包含核心逻辑的依赖。

一个折扣计算的对比例子

朴素版本:base=100, discount=10% → 90,只有一条,跑通即绿,什么都证明不了。

按上面的提示词生成出来的是另一批:折扣为 0% 时返回原价;折扣为 100% 时返回 0 而不是负数;折扣超过 100% 时的处理策略(拒绝还是允许负数,测试会逼你做出决定);负原价应报错;会员折扣与折扣的叠加顺序是否符合业务规则;金额落在 19.995 这种分位边界时是向上、向下还是四舍六入五成双。

差别在于:后者会暴露需求里的模糊地带,前者只会让报告好看。

一个便宜又好用的技巧:生成完之后,让 AI 反过来审查它自己写的测试——”指出这些测试里哪些断言在实现出错时仍然会通过,哪些 mock 过度了”。这一步能抓出相当比例的浅测试,成本几乎为零。

三个必须人工把关的地方

  • 依赖真实数据库的测试:AI 会写看起来对但悄悄跳过关键步骤的版本。
  • 时间、随机数、并发相关的测试:不确定性的输入 AI 看不见,断言往往凭空假设。
  • 快照测试(snapshot):AI 很喜欢生成,但它只是把当前输出拍平存下来,改动即通过,几乎没有回归价值,建议少用。

团队协作上的建议

把上面四步写进项目规则文件,让每个成员调用 AI 时都用同一套指令,产出质量才稳定。测试生成完记得走一遍AI 代码审查工作流,把”AI 写测试、 AI 审测试、人做判断”这条线跑顺;补测试的场景也可以结合GitHub Copilot 免费额度的用法,把额度用在刀刃上。另外,Cline 这类能自己跑测试并迭代的插件在整包补测试时效率最高,因为它能根据红色失败反复修。


AI 生成的单元测试覆盖率很高,为什么线上还是有 bug?
覆盖率只说明代码被执行过,不说明行为被验证过。常见的”虚假覆盖率”是断言恒真(只判断列表非空、对象非 null),覆盖率报表很漂亮,业务风险点一个没测。按分支清单下指令并逐条审断言,才能把覆盖率转成有效性。

应该喂实现代码还是需求文档给 AI?
优先喂需求文档、接口说明或 PRD 。只喂实现代码时,模型会把代码里的 bug 当成正确行为写进断言,等于把缺陷固化成契约。两者都给最好:需求定义”什么是对”,实现提供”怎么调用”。

集成测试和并发测试可以用 AI 生成吗?
不建议直接采用。这类测试依赖真实数据库、容器、时序和共享状态,AI 看不见这些前提,容易产出跳过关键步骤的”看起来合理”版本。要么自己写,要么对生成结果逐行审查后再合入。

快照测试值得让 AI 批量生成吗?
价值有限。快照测试把当前输出固化下来,实现一改只要更新快照就能通过,回归检测能力很弱。建议只在序列化格式、 API 响应结构这类”输出必须逐字节稳定”的场景使用。

看 AI 代码审查工作流怎么搭
这篇有帮助吗?
云上的幻象
云上的幻象查看主页

七彩云博客,分享 WordPress 建站实战与 AI 工具测评,覆盖服务器运维、站长工具、软件资源与电商运营干货,专注原创实用的主题插件、网站加速与安全优化教程。

795文章4评论

相关文章

评论 (0)

欢迎你,新朋友,感谢参与互动!文明发言,理性交流 · 首次评论将在审核后展示