给AI喂了100个历史Bug,它现在能帮我写断言了

简介: 上月接手历史项目,单元测试覆盖率仅21%。通过“AI调教三步法”:喂入百条真实Bug构建业务上下文、定制提示词模板、引入变异测试(PITest)严控断言质量,两周内将覆盖率提升至82%,并发现7个幽灵Bug。

上个月,我被拉进了一个“历史遗留项目攻坚群”。这个项目有多老?老到它的单元测试覆盖率常年趴在21%,每次上线前,测试同学都要靠手工回归点得手指抽筋。组长拍着我的肩膀说:“给你两周,把覆盖率干到60%以上。”

我当时的表情,大概就和看到自己写的代码在线上炸了一样——生无可恋。

硬着头皮写了两天单元测试,那叫一个痛苦。一个复杂的工具类,我要先 Mock 一堆 Service,再想各种边界条件,最后还得手写断言。我盯着屏幕想:这种重复劳动,能不能让AI替我干了?

于是我开始了为期两周的“AI调教计划”。过程有点曲折,但结果还真成了——覆盖率最终飙到了82%。今天就来聊聊,我是怎么把AI从“只会复制代码的实习生”,培养成“懂业务逻辑的测试老手”的。

第一阶段:理想很丰满,现实很骨感
我的想法很简单:直接把那些“祖传代码”扔给 ChatGPT,让它帮我写测试。

我从一个核心的业务 Util 类开始,复制了 200 多行代码,附上指令:“请为这个类编写完整的 JUnit 测试,使用 Mockito,要覆盖所有分支。”

AI 反应很快,10 秒钟就给我吐了一个上百行的测试类。我满怀期待地粘贴到 IDEA 里,然后点击运行——满屏飘红。

报错信息五花八门:NoSuchMethodError、NullPointerException,甚至还有 Mockito cannot mock this class。我仔细一看,发现 AI 干了几件蠢事:

它 Mock 了一个 final 类,但项目是老旧的 Java 8,Mockito 默认不支持 Mock final 。
它 Mock 了一个私有方法,这显然不符合常规的单测规范。
它生成的断言全是 Assert.assertNotNull(result)。这种断言有什么用?只要方法不返回 null,就算是把代码逻辑全删了,测试都能过。
第一个教训很深刻:AI 不知道你的项目上下文,它只是个无情的代码生成器,不是测试架构师。 它不知道你项目里有哪些框架限制,更不知道那些隐藏在 Spring 配置文件里的 Bean 该怎么注入。

第二阶段:把 AI 当实习生带,给业务上下文
既然 AI 不懂业务,那我就教它。

我开始换策略,不再一股脑地扔代码,而是当一个“翻译官”,把技术语言翻译成AI能理解的自然语言。我把过去一年这个模块修过的 100 多个 Bug 记录(那些让团队加过班的血泪史)整理出来,按类型打上标签。

这100个Bug就像一本错题集,涵盖了各种容易出错的场景:边界值遗漏、并发问题、Null 指针、异常处理不充分等等。

然后,我设计了一套“提示词模板”,每次让 AI 生成测试前,我都会告诉它:

“请为以下方法生成测试用例。该方法属于订单模块,调用方是营销中台。需要覆盖的场景: 1. 正常流程(参考历史Bug #45,注意金额为0的情况);2. 外部接口超时(参考Bug #12,需模拟TimeoutException);3. 会员等级为空(参考Bug #78,此场景应返回默认折扣,而非抛异常)。代码片段如下:

public BigDecimal calculateDiscount(String userId, BigDecimal amount) { ... }
断言要求: 对于金额比较,必须使用 compareTo 而非 equals,避免精度问题。"

结果出乎意料的好。

AI 生成的测试,终于不再是那种“跑个过场”的代码了。它会自动生成类似这样的测试,精准地覆盖我指定的边界:

@Test
void testCalculateDiscount_WhenMembershipApiTimeout_ShouldReturnDefaultDiscount() {
// 模拟历史Bug #12 的场景
when(membershipClient.getLevel(anyString())).thenThrow(new TimeoutException());
BigDecimal result = orderService.calculateDiscount("user123", new BigDecimal("100.00"));
// 验证是否返回了兜底的默认折扣,而不是报错
assertEquals(0, new BigDecimal("1.00").compareTo(result));
}
第二个教训(或者说心得):AI 的能力上限,取决于你喂给它的上下文下限。 你把历史 Bug 喂给它,它才知道哪里最容易出 Bug;你告诉它业务逻辑,它才能写出贴合场景的断言 。

第三阶段:批量流水线,让 AI 打工,我做监工
一个方法一个方法地调教,虽然比手写快,但还不够。我要的是批量化生产。

我写了一个简单的 Python 脚本,做了个简陋的“AI 单测生成流水线”:

扫描:扫描项目里那些覆盖率低于 50% 的类。
提取:解析该类的方法签名和依赖。
检索:从我们整理的历史 Bug 库中,检索与该类相关的历史缺陷场景。
生成:调用大模型 API,并把我设计好的“提示词模板”(包含业务描述、历史 Bug 场景、代码片段)传给它。
写入:将生成的代码写入对应的测试文件。
当然,第一次跑批量,翻车率高达 60%。主要问题集中在断言太弱上。

比如,AI 生成了一段代码,测试一个修改用户信息的方法。它的断言是:

Assertions.assertThat(updatedUser).isNotNull();
这个方法执行后,到底有没有修改成功?isNotNull 根本说明不了问题。这就是所谓的“覆盖率高,但质量低”,行覆盖率上去了,但代码里的逻辑错误,它一个也抓不出来。

这让我想到了一个更严格的检验标准:变异测试。

我在一个核心模块上跑了一下 PITest,结果让人崩溃——变异测试覆盖率只有 20%。这意味着,即使我改了代码的逻辑(比如把 if(level == "GOLD") 改成 if(level != "GOLD")),AI 生成的测试也不会失败,因为它的断言太弱了,根本没有验证核心结果 。

第四阶段:锻造“火眼金睛”,教 AI 写有效断言
既然问题出在断言上,那我就专门针对“断言”进行特训。

我收集了项目组里公认写得最好的20个手写测试用例,把它们作为“范文”喂给 AI,并告诉它:“学习这些断言的写法,不要只判断空,要判断结果是否符合预期。”

同时,我在提示词里增加了“断言模式”:

对于查询类方法:必须验证返回值的关键字段。
对于更新类方法:必须通过 Verify 模式验证依赖服务的方法被正确调用,且参数正确。
对于异常类测试:必须验证异常类型和异常消息(因为很多时候不同的异常由不同的错误码映射,消息也很重要)。
对于集合类:必须验证集合的大小和包含元素,而不是只断言不为空。
经过几轮优化,AI 生成的断言终于像那么回事了。比如针对上面的更新方法,它现在会写成这样:

@Test
void updateUser_ShouldModifyUserName_WhenInputIsValid() {
// ...
userService.updateUser(request);
// 有效的断言:验证数据库里的实体真的被改了
User actualUser = userRepository.findById(userId);
assertThat(actualUser.getName()).isEqualTo("新名字");
// 并且发送了领域事件
verify(eventPublisher).publishEvent(any(UserUpdatedEvent.class));
}
最后,我再次运行 PITest,这次变异测试覆盖率从 20% 涨到了 67%。虽然离 100% 还有距离,但至少现在 AI 写的测试,是真的能“杀死”变异体、保护代码逻辑的了。

写在最后
两周时间,我几乎没怎么写“硬代码”,但通过“人指挥 AI + 历史数据喂养 + 变异测试验证”这套组合拳,硬是把那个“祖传项目”的单元测试覆盖率从 21% 拉到了 82%。更重要的是,在这个过程中,AI 帮我发现了 7 个隐藏的 Bug,都是那种只有在极端边界条件下才会触发的“幽灵 Bug”。

现在的我,每天的工作不再是埋头写枯燥的 assertEquals,而是琢磨怎么优化提示词,怎么整理更好的历史数据喂给 AI,以及怎么通过变异测试的报告来反向要求 AI 写出更高质量的断言。

如果你也想让 AI 帮你写测试,我的建议是:别把它当神仙,把它当徒弟。给它看错题集,它才能考高分。

相关文章
|
8月前
|
人工智能 缓存 监控
AI 说 Bug 在这,你信吗?一套方法让你用 AI 定位不再踩坑
本文探讨AI在Bug定位中的实战应用:如何用AI高效梳理现象、生成可验证的假设清单、关联日志与代码,同时规避幻觉风险;明确AI是“辅助思考的定位助手”,而非替代者,并提供可落地的四步工作流与主流工具使用指南。
|
Ubuntu 安全 Linux
不用安装虚拟机,直接在Windows上面运行Linux Bash Shell,嗯!真香!!!
不用安装虚拟机,直接在Windows上面运行Linux Bash Shell,嗯!真香!!!
1615 0
|
8月前
|
人工智能 自然语言处理 测试技术
Prompt Engineering 进阶:如何写出让 AI 自动生成高质量测试用例的提示词?
AI赋能测试用例设计,关键在结构化Prompt:需明确角色、业务、技术栈与约束,并融入等价类、状态图等测试方法论;要求表格化/代码化输出,辅以少样本示例和异常场景深挖。本质是将测试经验精准传递给AI。
|
8月前
|
人工智能 JSON 自然语言处理
别手写断言了!Copilot for Testing 让我提前两小时下班
本文分享作者如何用GitHub Copilot智能生成接口测试断言,提升自动化测试质量与效率:告别手写冗余断言,通过自然语言描述、示例引导和缺失检查,实现“断言全覆盖”;实测断言编写提速3倍、覆盖更全、错误更少,让测试真正从“跑通”迈向“测对”。
|
8月前
|
人工智能 测试技术
AI 写的测试用例,你敢直接用吗?这套判断方法,很多团队正在用
本文直击AI写测试用例的核心矛盾:不问“会不会写”,而聚焦“能不能用”。提出四大落地判断标准——业务贴合度、可执行性、异常覆盖力、规范一致性,帮测试工程师快速甄别AI用例价值,实现从“生成即用”到“工程化采纳”的跃升。
|
8月前
|
人工智能 运维 安全
2026年阿里云OpenClaw(Clawdbot)极速部署+ZeroNews Gateway Dashboard 远程管理指南
在2026年AI智能体技术落地加速的背景下,OpenClaw(原Clawdbot,曾用名Moltbot)作为高性能AI智能体网关平台,凭借私有化部署、全场景技能拓展、轻量化运行的核心优势,成为个人开发者与企业搭建专属智能工作系统的首选。其核心操作界面Gateway Dashboard集成了模型配置、技能插件管理、渠道对接等全量功能,但默认仅支持本地局域网访问,官方推荐的Tailscale、VPN等远程方案在国内网络环境中存在延迟高、配置复杂等问题。而ZeroNews凭借轻量化部署、专属域名映射、多重安全防护的特性,成为适配国内网络的OpenClaw远程管理最优解。
1587 16
|
7月前
|
人工智能 IDE 测试技术
接口文档一丢,AI自动生成测试用例和自动化脚本?
AI IDE + MCP 正重塑软件测试:需求文档→AI自动生成测试用例与自动化脚本→CI自动执行。相比传统人工编写,它大幅提升效率;区别于知识库方案,AI IDE可操作文件、调用API、构建工程。核心前提:需求需结构化、清晰。
|
8月前
|
人工智能 安全 搜索推荐
2026年OpenClaw/Clawdbot效率革命:阿里云部署+6大岗位必备Skills实战指南
2026年,AI工具的应用早已不是"会不会用"的选择题,而是"怎么用"的淘汰赛。OpenClaw(原Clawdbot)作为AI自动化领域的核心工具,凭借可扩展的Skills生态,正成为各岗位的"效率外挂"——它能将重复的工作流程封装为标准化技能包,让AI记住你的工作方式,无需反复调教即可自动完成任务。
1046 17
|
8月前
|
人工智能 算法 API
当AI开始胡说八道:我们如何测试大模型的“幻觉”问题
本文以真实案例切入,深入解析大模型“幻觉”现象——AI看似合理却事实错误的生成内容。系统梳理事实性、逻辑性、指令性等幻觉类型,分享知识库比对、逻辑自检、对抗测试、边界压力等实战检测方法,并提出分级修复策略与“降低频率、增强可识别性、关键场景防护”的治理思路,倡导以“可靠”而非“绝对正确”为目标的AI测试新范式。

热门文章

最新文章