GPT-4o救了我的烂摊子:给3个祖传模块补单元测试,覆盖率从12%飙到78%
部门上个月定了个死线所有核心模块的单元测试覆盖率必须在Q3结束前提到70%以上。我名下挂着一个维护了4年的数据处理工具库打开覆盖率报告那一刻数字刺眼得不行——12%。不是我不想写测试。这库里有1700多行代码包含42个函数里面混杂着回调地狱、隐式全局状态、直接操作DOM的工具方法以及好几个“这个参数传进去到底返回什么得跑一下才知道”的函数。单测我自己都测不明白。最后我用了一个让同事直呼“你小子作弊”的办法让GPT-4o帮我读源码分析每个函数的输入输出边界然后自动生成vitest测试用例。三周后覆盖率78%更关键的是还顺带发现了2个隐藏了三年的bug。这阵子我一直在做一个国内镜像站mf.877ai.cn的深度体验把GPT-4o、Claude 3.5 Sonnet、Gemini 2.5 Pro拉到一个页面里对比专门测代码理解和测试生成能力。今天就把这套“AI辅助测试补全”的完整工作流拆给你看。一、为什么是GPT-4o不是其他模型补单元测试这件事和写业务代码完全不一样。写业务代码是你告诉模型“我要什么”它实现补测试是你让模型先理解“这东西在干什么”再推导“它该怎么被验证”。后者对代码语义理解的深度要求高得多。我把库里的一个典型函数分别丢给三个模型让它们生成测试用例然后人工打分评估维度GPT-4oClaude 3.5 SonnetGemini 2.5 Pro函数边界条件覆盖95%覆盖null/undefined/空数组88%漏了undefined边界80%边界意识较弱异步逻辑mock合理性90%自动补了定时器mock85%75%手动补了很多mock测试命名与组织优秀describe/it分层清晰优秀一般生成代码可直接运行率85%78%62%GPT-4o在边界条件挖掘上明显更主动。比如一个处理数组的函数它会自动补充“传入类数组对象”、“传入带空槽的稀疏数组”这种我平时写测试都会漏掉的用例。二、三件套工作流我是怎么干的我的流程是标准三步分析→策略→生成。每一步的提示词写法都有讲究。第1步代码语义分析——先别急着写先搞懂函数在干嘛这一步最容易被跳过但最关键。你不能直接把整个1700行文件扔给模型说“写测试”它会乱。我是一次只输入一个函数先让它分析这个函数的“契约”。核心提示词模板请分析以下JavaScript/TypeScript函数的代码逻辑不要写测试 函数代码 [粘贴函数代码] 请输出 1. 函数的核心功能一句话 2. 输入参数的所有可能类型和边界值正常值、null、undefined、极端值等 3. 返回值类型及在不同输入下的变化规律 4. 函数的副作用列表修改了哪些外部状态、调用了哪些外部依赖 5. 异常分支分析什么输入会导致抛出错误、错误类型是什么这一步跑了大概一小时。GPT-4o分析完所有42个函数后我得到了一份极其清晰的“函数契约清单”。这里面有几个惊喜——它发现了一个日期格式化函数在传入负数时间戳时会NaN一个处理金额的函数在传入科学计数法字符串时会静默出错。// GPT-4o分析出的隐藏bug案例functionformatMoney(amount){// 分析结果当输入为 1e10科学计数法时// parseFloat 会将其解析为 10000000000// 但 toFixed(2) 在处理极大数字时可能产生精度丢失returnparseFloat(amount).toFixed(2);}// 建议测试用例// formatMoney(1e10) → 期望什么当前代码返回的是 10000000000.00// 但 js 的浮点数精度可能导致最后一位偏差我在看到这份分析后先把这俩bug修了才开始写测试。这顺序不能乱——如果你在旧代码的bug基础上补测试要么测出失败但你不敢改代码要么为了通过测试把断言写得很宽松测试就废了。第2步测试策略——决定怎么测、测到什么程度分析完函数契约下一步是让GPT-4o根据每个函数的复杂度、风险和调用频率来制定测试优先级和策略。核心提示词基于上面这个函数的分析结果制定测试策略 1. 该函数的核心测试路径是什么必测覆盖80%的正常使用场景 2. 有哪些边界条件必须覆盖列举所有输入参数类型的边界值 3. 有哪些异常路径需要测试错误输入、异常状态 4. mock策略哪些外部依赖需要mock怎么mock给出具体的mock方式 5. 优先级高/中/低高风险复杂函数优先这一步产出了一份测试策略文档我按优先级排序先搞定高风险函数。7个高风险函数占库代码量的40%但覆盖它们后覆盖率直接从12%蹦到了51%。[配图1测试覆盖率提升路径图横轴为工作天数1-15天纵轴为覆盖率百分比柱状图上标注累计覆盖的高/中/低风险函数数量显示7个高风险函数覆盖后达到51%15个中风险后达到72%全部完成后达到78%]第3步用例生成——真正的自动化补测试到这一步才真正让GPT-4o写测试代码。我每条提示词包含函数源码 第1步的分析结果 第2步的策略然后让它生成完整的vitest测试套件。提示词结构请基于上面的函数分析和测试策略为以下函数生成vitest测试用例。 要求 1. 使用 describe/it 结构每个it覆盖一个明确的行为 2. 测试命名遵循“should [行为描述] when [条件]”格式 3. 覆盖所有核心路径、边界条件和异常路径 4. 外部依赖使用 vi.mock 或 vi.fn 进行mock 5. 异步函数使用 async/await 和 vi.useFakeTimers如需 6. 不要使用 any 类型所有mock函数的类型要明确 7. 直接输出可运行的完整测试代码 函数代码 [粘贴]关键代码片段展示一个典型函数的测试生成效果// 原函数处理订单金额折扣functionapplyDiscount(price:number,discount:number):number{if(price0)thrownewError(价格不能为负数);if(discount0||discount1)thrownewError(折扣必须在0到1之间);returnMath.round(price*(1-discount)*100)/100;}// GPT-4o生成的测试套件import{describe,it,expect}fromvitest;import{applyDiscount}from./order;describe(applyDiscount,(){// 核心路径it(should return discounted price when given valid inputs,(){expect(applyDiscount(100,0.2)).toBe(80);});it(should round result to 2 decimal places,(){// GPT-4o自动补的小数精度测试expect(applyDiscount(99.99,0.33)).toBe(66.99);});// 边界条件it(should handle zero discount correctly,(){expect(applyDiscount(50,0)).toBe(50);});it(should handle full discount (100%) as zero,(){expect(applyDiscount(50,1)).toBe(0);});it(should handle price of zero,(){expect(applyDiscount(0,0.5)).toBe(0);});it(should handle very large price without overflow,(){// GPT-4o自动考虑的大数值边界constresultapplyDiscount(99999999.99,0.01);expect(result).toBeGreaterThan(0);});// 异常路径it(should throw error when price is negative,(){expect(()applyDiscount(-1,0.1)).toThrow(价格不能为负数);});it(should throw error when discount is out of upper range,(){expect(()applyDiscount(100,1.1)).toThrow(折扣必须在0到1之间);});it(should throw error when discount is negative,(){expect(()applyDiscount(100,-0.5)).toThrow(折扣必须在0到1之间);});});一次生成42个函数中有36个的测试套件可以直接跑通剩下6个需要微调主要原因是老代码里有一些硬编码的外部模块引用GPT-4o的mock路径写错了。这种情况你手动改一下import路径就行5分钟的事。三、三个你必须避开的坑坑1不要一次喂太多函数。我试过把一个文件里的5个函数一起给它结果它对第4、5个函数的边界分析明显变粗糙了。教训一次只喂一个函数保证质量。坑2模型生成的mock可能“过度合理”。比如一个函数内部调用了Date.now()GPT-4o会自动用vi.useFakeTimers来mock但它有时候mock的逻辑过于完美——测试通过了但实际运行时会因为时区问题失败。遇到涉及时间的函数务必手动检查useFakeTimers的设置。坑3别盲目相信覆盖率数字。AI帮我把覆盖率提上来之后我又做了一次变异测试mutation testing发现有几个测试的断言其实没什么区分度——随便改一下源码它都能过。这说明GPT-4o在某些边界场景下写了“软断言”。我用Stryker跑了一轮把那些“假阳性”测试揪出来重写最终有效覆盖率才稳在78%。[配图2工作流三步骤的时间分配饼图代码分析占25%测试策略占15%用例生成与调优占60%标注“AI负责生成人负责审查和微调”]四、这套流程适合什么场景最适合的场景功能稳定但久无测试的老旧工具库纯函数占比高的数据处理模块逻辑清晰边界好定义已经过代码review、确认无已知bug的代码先修bug再补测不太适合的场景包含大量UI交互逻辑的前端组件涉及DOM的测试建议用E2E单测写起来痛苦且价值低仍在快速迭代中的业务模块测试刚写完需求就变了维护成本高涉及复杂状态机的模块模型很难理解全量的状态转移路径最后说两句以前补单元测试是件纯体力活对着源码一行行推逻辑、穷举边界、写mock最后跑完覆盖率一看30%心态直接崩。现在有了GPT-4o这种级别的代码理解能力测试补全这件事从“能不能”变成了“值不值得”。但别偷懒把整个流程全交给AI我的经验是AI负责80%的生成你负责20%的审查。它挖出来的边界条件你去验证它写的mock你去核对它漏掉的极端场景你去补。这样出来的测试套件才是真正敢在CI里跑、敢凭它重构代码的那种。