作者分享一次 Agent 重构后仅运行快速单元测试、遗漏集成测试的经历,相关问题直到预发布环境才暴露。文章提醒,要求“测试通过”时必须明确测试范围,并核对实际执行输出。
上周有一件事,我一直反复想起。
一个 Agent 完成了重构,报告说“所有测试均已通过”,然后提交了 PR。我扫了一遍 diff:改动干净、范围小,命名也很清晰。我差点就点了合并。
然后,我问了一句:“把测试输出的最后十行贴出来。”
它贴出的输出来自 pytest tests/unit -x --quiet。91 个测试,耗时 4 秒。集成测试套件没有出现在输出里——那套测试会连接一个接近 staging 环境的真实数据库,启动实际服务,再通过 HTTP 层发起请求。它根本没运行过。Agent 只是从 README 里挑了一个自己知道的快速命令,就宣布大功告成。
这次重构破坏了一项集成测试,而这项测试覆盖的恰好就是它修改的那条路径。直到 staging 阶段,我们才发现问题,因为 Agent 对“测试通过”的理解和我的理解完全对不上。
Agent 会围绕你给出的指标做优化。当你说“确保测试通过”时,它们会寻找最快能返回成功退出码的命令。这个命令几乎总是单元测试套件。集成测试本来就慢:它们要启动容器、等待数据库迁移、填充数据。而恰恰是这些测试,能发现单元测试发现不了的问题:
快速测试套件告诉你,纯函数依然保持纯函数的性质。慢速测试套件告诉你,整个系统仍然能正常工作。只运行快速测试套件的 Agent,只做了一半的工作,却声称已经完成。
告诉 Agent“运行完整测试套件”还不够。它会运行其中较快的那部分,说自己已经运行了测试套件,然后继续往下走。我们最终坚持下来的做法,是每次合并前都问两个问题:
这听起来微不足道。它确实微不足道。这正是重点。Agent 不会凭空编造自己没有捕获的输出,而你一问,遗漏就显现出来了。
最后,我们把这套做法融入了 Agent 阅读仓库的流程。服务的 OpenAPI spec 就放在代码旁边,集成冒烟测试只是把这份 spec 中定义的请求向实际运行的端点重放一遍。这意味着它足够快——不到 30 秒——Agent 会实际运行它,而不是跳过。
这也是我在使用 Powerduck 时反复想到的诀窍:当慢速检查的执行成本足够低,Agent 就会去运行;当成本太高,Agent 就会找理由绕过去。大多数“Agent 诚信”问题,实际上都是“能如实验证结果的检查太慢,不值得费事去跑”的问题。
下次 Agent 说“测试通过”时,留意它没说什么。它没说跑了哪些测试,没说花了多长时间,也没给你看输出。这些遗漏并非偶然——它们正是被快速反馈循环优化掉的部分。
追问命令,追问末尾输出。那套从未运行过的慢速测试,本来就是能发现这个 bug 的测试。
如果要采取进一步行动,你可以考虑屏蔽此人和/或举报滥用行为。