用AI为遗留代码补单元测试:从首个可运行用例到排错清单
先确定目标:记录现状,不让AI猜需求
给遗留代码补单元测试,最大的风险不是测试跑不通,而是测试通过了,却验证了错误的业务规则。正确顺序是:确认现有行为、隔离外部依赖、生成小批用例、人工审核断言。不要一开始就要求AI重构整个模块。
优先选择近期要修改、调用频繁且输入输出较清晰的函数。例如订单折扣计算,比同时访问数据库、发送邮件和写日志的完整结算流程更适合作为起点。
第一步:准备能复现的最小上下文
- 提供目标函数、直接调用的辅助函数、数据结构和异常类型,避免只贴一段缺少依赖的代码。
- 说明语言版本、测试框架、目录结构,以及项目现有测试的写法。
- 附上经过脱敏的输入输出样例,区分“已确认规则”和“观察到但尚未确认的行为”。
- 先运行现有测试并记录失败项,避免把环境问题误判为新测试造成的回归。
缺少业务文档时,可先写特征测试:记录当前实现对固定输入的实际响应。它能保护现状,但不能证明现状正确;遇到疑似缺陷,应单独标注并交给业务负责人确认。
第二步:用明确提示词生成首批测试
可以这样要求AI:“使用pytest为订单折扣函数生成单元测试。先列出正常、边界和异常场景,以及每个场景的依据;依据不足时提问,不要编造规则。禁止修改生产代码,禁止访问真实网络或数据库。沿用项目测试风格,先生成五个用例,并解释模拟对象应替换在哪个命名空间。”
审核时逐个检查:输入是否真实可构造、预期结果是否有独立依据、异常是否精确到类型。金额计算要遵守原有精度和舍入规则,不要让AI擅自把十进制定点金额改成浮点近似比较。
第三步:实际运行,再按错误类别修复
以Python项目为例,先执行 python -m pytest tests/test_discount.py -q。安装并配置pytest-cov后,再执行 python -m pytest tests/test_discount.py --cov=legacy.discount --cov-branch --cov-report=term-missing,其中模块路径应替换成项目实际路径。
- 导入失败:检查包安装方式、工作目录和测试配置;不要直接复制生产代码到测试文件里绕过导入。
- 断言失败:先核对业务规则与真实执行结果,再判断是测试写错还是实现有缺陷,不要为了变绿直接改预期值。
- 环境失败:补齐依赖和必要配置,明确哪些测试需要基础设施,不把它们伪装成纯单元测试。
常见问题:为什么模拟了请求,测试仍然联网?
通常是替换位置错误。若 legacy.billing 使用 from gateway import charge,测试一般应替换 legacy.billing.charge,而不是只替换 gateway.charge。原则是在被测代码查找对象的位置替换它。
可使用 autospec=True 约束调用签名,减少不存在的方法也能被模拟成功的问题。时间、随机数和环境变量同样需要固定;数据库与网络应在单元测试边界隔离,真实交互另设集成测试。
常见问题:覆盖率很高,为什么还是漏掉缺陷?
行覆盖只说明代码被执行,不说明断言有效。重点检查空集合、零值、阈值两侧、依赖超时和异常传播;对返回结果、必要副作用及禁止发生的操作分别断言。
可在临时分支或使用变异测试工具,把关键比较符从“大于”改为“大于等于”,观察测试是否失败。如果仍然通过,通常需要补充边界用例。验证后恢复代码,不把故意植入的错误提交。
常见问题:怎样降低AI调用成本并安全接入?
不要每轮发送整个仓库。先提交目标模块和测试约定,失败后只补充相关代码、错误堆栈与已有断言。场景梳理和模板生成可先用较低成本模型,复杂依赖分析再交给能力更强的模型。
59API提供Claude、GPT等原生官方品质模型,不做降级,按量计费且价格低,适合补测时反复生成与验证。它兼容Claude Code、Codex及OpenAI SDK,网关地址为 https://api.59api.com;具体模型标识、鉴权和路径配置以接入说明为准。若希望先用小模块验证效果,可以注册59API,小额试跑并比较每批测试的实际成本;平台也提供推荐返利。
提交代码前先脱敏密钥、客户数据和内部地址,并确认组织允许使用第三方服务。最终验收标准不是生成了多少测试,而是:测试可重复运行、断言有依据、能拦截真实回归,且没有未经审核的生产代码改动。