让AI补齐单元测试,覆盖率从40%提到78%的过程
接手的老服务单测覆盖率41%,补测的活排了三个季度没动。用AI流水线批量补测,三周把覆盖率推到78%,记录方法论和返工细节。
第一步,选靶子。不是所有文件都值得补:按变更频率乘复杂度的乘积排序, 前二十个模块占了线上问题的七成,优先打这些。纯数据结构的DTO类直接放弃,AI生成的getter测试毫无价值还污染覆盖率数字。
第二步,生成策略。逐函数生成而不是逐文件,上下文聚焦时质量明显更好。prompt里带三样东西:函数源码、它依赖的接口签名、同仓库已有的测试风格示例,最后一样最重要,能让AI写出风格统一的用例,review时不用切换阅读习惯。
def gen_tests(func_src, deps, style_examples):
prompt = f'''为以下函数写 pytest 单元测试:
- 覆盖正常路径、边界值、异常输入
- mock 外部依赖,不打真实网络
- 风格参考:{style_examples}
函数:{func_src}
依赖:{deps}'''
return llm_complete(prompt, temperature=0.2)
第三步,质量闸门,这是成败手。AI生成的测试有三个高频病:断言太弱,只测不抛异常;mock过度,把被测逻辑本身也mock掉了,测试永远绿;自证式断言,用实现算期望值再断言相等。流水线里加两道机械检查:覆盖率增量低于阈值的用例丢弃;跑变异测试抽样,杀不掉变异体的测试视为伪测试。
三周的实测数据:生成用例约4200个,通过闸门保留2900个,人工review的重点从写测试变成删测试,工作量降一个数量级。覆盖率41%到78%,剩下的22%是长尾的副作用函数和集成边界,留给人工补关键路径。
一个反直觉的收获:AI补测过程中暴露了11个真实的边界bug,空列表切片、除零、时区错位,这些函数原本裸奔在线上。测试覆盖率是手段,顺手抓虫才是意外的主菜。
AI测试的长期维护问题补充,这是三个月后暴露的新课题。AI生成的测试和实现耦合过紧,重构时测试批量红,区分"行为变了"和"写法变了"的成本上升,我们后来立了规矩:断言只针对公开契约,内部实现的细节不测,AI生成时在prompt里显式约束这一点,重构抗性明显改善。另一个观察是覆盖率的边际效应,78%之后每提一个点,伪测试比例显著上升,90%以上的数字开始变成行为艺术,我们把目标定在80%就收手,省下的精力转投集成测试,回归价值更高。工具是好工具,但测试的策略和边界,人必须自己想清楚。
- 点赞
- 收藏
- 关注作者
评论(0)