用 AI 自动写代码最怕的不是它写不出来,而是它把一个错误的假设写得极其完美
很多人觉得只要给 AI 一个需求,然后让它写代码并配套写测试用例,只要测试通过了就万事大吉。但我最近在折腾一套密码重置流程时发现,这种「实现 + 测试」同步生成的闭环其实是个巨大的陷阱。
结论是:如果实现代码和测试代码由同一个 AI 基于同一个 Prompt 生成,它们会共享同一个认知盲区。即使测试全部通过,也可能隐藏着低级逻辑漏洞。
为什么「测试通过」不代表代码正确
我之前让 AI 帮我写个密码重置功能,它写得飞快,Happy Path 跑得非常顺畅,配套的单元测试也全绿。结果上线后我才发现,重置链接居然可以重复使用。
这在常识里应该是「单次有效」,但我在 Prompt 里没写死。AI 默认实现成了「只要 Token 没过期就能用」。因为它在写测试用例时,也潜意识地认为「只要 Token 有效就能重置成功」是对的。于是,它写了一套验证「成功路径」的测试,而没有写验证「重复使用应当失败」的测试。
这就是典型的「共享错误假设」。实现者和验证者在用同一把错误的尺子量东西,结果当然是完美契合。
独立行为规范比增加测试量更重要
为了解决这个问题,我尝试改变工作流,不再让 AI 一次性出代码和测试,而是强行拆分出「行为规范(Behavioral Specification)」这一步。
我写了一份独立于代码的规范文档,明确要求:
- 重置 Token 必须在第一次消费后立即失效。
- 第二次尝试使用同一 Token 必须返回 400 或 403。
然后让 AI 根据这份规范去实现,再由另一个独立的验证步骤去跑。这样确实拦截到了重复使用的 Bug。但随后我发现,即便有了规范,如果规范本身是不完整的,AI 依然会掉坑里。
比如并发请求。如果两个请求在同一毫秒到达,且代码逻辑是:
1. 检查 Token 是否有效 → 有效
2. 执行重置 → 成功
3. 将 Token 标记为已使用
那么在第一步和第三步之间,第二个请求已经通过了检查。结果就是「单次有效」的逻辑在并发环境下失效了。
怎么避免 AI 陷入「认知闭环」
如果你也在用 Cursor 或 Claude Code 做功能开发,千万不要直接说 Write the feature and its tests。建议尝试以下实操方案:
1. 强行引入「对抗性」角色
不要只让 AI 写测试,要给它一个「破坏者」的 Persona。在生成测试前,先跑一个 Prompt 专门挖掘边界 case:
你现在是一个极其刻薄的 QA 工程师,你的目标是证明这个功能实现是有漏洞的。
请列出 5 个可能导致该功能在极端情况下(如并发、网络延迟、非法输入)崩溃的场景,
不要考虑 Happy Path,只写 Edge Cases。
拿到这个列表后,再把这些场景转化为具体的测试用例,最后才交给 AI 去实现。
2. 验证逻辑的原子性
对于像 Token 消费这类关键操作,不要信任 AI 默认的 if-else 判断。在 Review 代码时,重点检查它是否使用了原子操作。比如在 PostgreSQL 中,你应该检查它是否用了 UPDATE ... WHERE token = 'xxx' AND used = false 这种带条件的更新,而不是先 SELECT 再 UPDATE。
3. 接受「规范是临时性的」
不要试图一次性写完完美的 Specification。真正的工程路径应该是:初步规范 → AI 实现 → 独立验证发现漏洞 → 修正规范 → 重新实现。
避坑总结
- 不要用同一套 Prompt 同时生成代码和测试,这会导致测试集变成实现的「回声」。
- 增加测试数量 ≠ 提高覆盖率。如果 AI 认为「重复使用是允许的」,它能给你写 100 个测试来证明这件事是「正确」的。
- 独立验证必须基于独立于代码的逻辑定义。

这不就是典型的需求坑吗,要是等到集成测试才发现没写负面用例,得返工多少个版本……