AI 写代码太奔放,我就用推理模型给它加上了极高强度的回归测试套件 (稳赢版)

AI写代码太奔放,我就用推理模型给它加上了极高强度的回归测试套件。这玩意儿现在是我的护城河,也是我的刹车片。Claude 3.5 Sonnet 或者 GPT-4o 生成一段业务逻辑,那速度确实快,但你看它那个劲头,恨不得把所有边界情况都用一个“优雅”的万能 if-else 给糊弄过去,代码里充满了“假设用户总是理性的”、“假设数据总是干净的”这种致命幻觉。去年我吃过一次大亏,一个自动处理电商订单的RPA流程,AI生成的脚本在99%的情况下丝滑无比,偏偏就在某个SKU库存突然跳变到负值时,逻辑链直接断裂,把半个数据库的状态给锁死了。从那次起我就明白了,在AI时代,你信任AI写代码的速度,就得承受它代码里埋的、你自己都想不到的雷。

所以我的策略彻底变了。我不再追求“一次生成,直接运行”。我的新流水线是:让生成模型(比如GPT)出第一版草稿,然后立刻把这段代码连同需求描述,扔给另一个专门调教过的推理模型(通常是Claude,因为它更“较真”),给它一个核心指令:“假设这段代码是你要审查的、一个急于求成的初级程序员写的,请为它设计一套极其严苛、甚至有些变态的回归测试用例。重点不是测试正常流程,而是穷尽所有你能想到的、能让这段代码崩溃、出错或产生歧义的边缘情况和异常输入。” 这个提示词是关键,它设定了对抗性的语境。

光有提示词不够,得给推理模型“武器”。我会把项目的上下文喂给它:数据表的Schema(特别标注哪些字段可为空、哪些有唯一约束)、调用的第三方API的文档摘要(重点是错误码和频率限制)、甚至是这个业务模块历史上真实出现过的生产事故报告。让推理模型站在一个拥有上帝视角的“破坏者”角度去思考。它生成测试用例的奔放程度,丝毫不亚于写代码的AI。它会设计出诸如“连续发送1000个并发请求触发API限流后,检查本地队列的积压处理和状态回滚是否一致”、“模拟数据库连接在事务中间突然断开,检查是否有半成品数据残留”、“输入一个包含Unicode表情符号、SQL注入片段和JSON断行的混合字符串作为参数”这种场景。这些用例,靠人脑在短时间内根本想不全。

接下来才是精髓:我不直接运行这些测试。我让推理模型再把这些测试用例,转换成对应编程语言(比如Python的pytest)的具体测试代码。这里有个微妙的控制点:我会要求测试代码必须包含清晰的断言信息,并且在每个测试用例前,用注释写明这个用例“试图证明什么缺陷”。这一步是把模糊的“破坏性想法”工程化的过程。生成测试代码后,我会用AI去检查这些测试代码本身的语法和逻辑是否有误——相当于用AI审计AI。

最后,把最初生成的业务代码,和这套“来自地狱的测试套件”放到一起,跑。结果通常是血腥的。最初那版“优雅”的代码会大面积飘红。这时,我会把测试失败的详细日志(包括断言失败信息、堆栈跟踪)反馈给最初的代码生成模型,命令它:“根据这些测试失败信息,修复你的代码。要求:1. 通过所有测试;2. 在代码关键节点添加日志和监控点;3. 为每一个修复的边界情况添加注释。” 这个过程可能会迭代2-3轮。

当所有测试用例(包括那些“变态”的)都通过时,这套代码的健壮性已经远超直接生成的版本了。更重要的是,这套测试套件本身成为了活的文档和守护程序。以后任何需求变更,需要修改这段代码时,我会先让AI理解这些现有的测试,然后基于新的需求去更新测试用例,最后再改代码。这看起来多花了好几倍的时间,但比起线上故障的排查成本、数据恢复的代价和客户信任的流失,这点前期投入太值了。AI写代码是“快”,但快的是第一个版本。而我的这套“生成-对抗测试-修复”的循环,求的是整个软件生命周期的“稳”。在一切都追求速成的AI狂欢里,我反而觉得,这种用AI来制造约束、用自动化来追求确定性的“慢”,才是真正的“快”。稳,才能赢到最后。

(记录:今天用这个方法为一个客户封装了一个数据清洗的GUI工具,测试用例覆盖了17个异常路径。客户试用零投诉。提示词库中“高强度回归测试”条目更新,划掉最后一行“通过的测试”改为“通过的、可解释的测试”。)

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享