AI 编程 Agent 说“测试通过”?它可能根本没运行测试

原文:https://dev.to/robertadam987_/your-ai-coding-agent-says-tests-pass-but-did-it-actually-run-them-4684(作者 @robertadam987_)

AI 编程 Agent 越来越擅长完成任务了。

它们会修改文件。

修复错误。

编写测试。

执行命令。

然后以类似这样的话收尾:

所有测试均已通过

而我们大多数人就直接翻篇了。

但有一个很重要的问题:

Agent 真的运行过它声称通过的测试吗?

这听起来是显而易见的。

其实不然。

因为在 AI 辅助开发中,我们正开始相信总结,而不是证据。


“测试通过”只是一个说法

设想一下 Agent 输出了这样的内容:

实现完成。

✓ 测试通过
✓ 构建成功
✓ 无 lint 错误


看起来让人很安心。

但你仍然不知道:

  • 它执行的是什么命令
  • 是否运行了完整的测试套件
  • 是否有部分测试被跳过了
  • 命令是否成功退出
  • 输出结果是否来自最新的代码
  • 它到底有没有运行过测试

这句话只是一份总结。

它不是证据。


这是一种新型的信任问题

在编程 Agent 出现之前,开发者通常直接运行命令:

npm test


你能看到输出。

能看到失败信息。

也能看到退出码。

而有了 Agent 之后,工作流可能变成:

开发者提出功能需求
        ↓
Agent 修改代码
        ↓
Agent 运行了某些东西
        ↓
Agent 总结执行结果
        ↓
开发者选择相信总结


现在,在你和真正的验证之间多了一层。

而这一层是可能出错的。


Agent 可能只运行了一部分测试

假设你的项目包含:

单元测试
集成测试
API 测试
端到端测试


Agent 运行了:

npm run test:unit


全部通过。

然后它汇报:

所有测试均已通过。

严格来说,确实有一些测试通过了。

但整个应用从未被完整验证过。

这个区别很关键。


它汇报的可能是过期结果

另一种很容易出现的失败模式:

Agent 运行测试
        ↓
测试通过
        ↓
Agent 又修改了代码
        ↓
Agent 汇报"测试通过"


这句话在当时是真的。

但现在可能已经不是了。

验证应该针对代码的最终状态来进行。


测试通过,仍可能意味着测试本身是错的

还有另一个问题。

AI 写完了功能。

接着 AI 写测试。

然后 AI 运行这些测试。

全部通过。

很好。

但问题在于:实现代码和测试代码可能共享着同一个误解。

比如:

对需求理解错了
        ↓
AI 写出代码
        ↓
AI 按同样的理解写测试
        ↓
测试通过


一片绿。

功能却仍然是错的。

所以真正的问题其实有两个:

测试真的运行过吗?

以及

它们本身是正确的测试吗?

两个都重要。


要证据,不要自信

我现在越来越倾向一条简单的规则:

如果 agent 声称完成了验证,就要求它出示背后的证据。

与其直接接受一句:

测试通过。

不如要求它给出:

给我看:

1. 你运行的确切命令
2. 退出码
3. 一共运行了多少个测试
4. 多少个失败
5. 多少个被跳过
6. 是否是在最后一次代码修改之后运行的


这样一来,声明就变得可查验了。


给你的 agent 一份“验证契约”

你可以把这件事写进日常的编码 agent 指令里。

例如:

永远不要说“测试通过”,除非你确实运行了相关的测试命令。

报告验证结果时,必须包含:

- 确切运行的命令
- 退出码
- 测试总数
- 失败数
- 跳过数
- 构建状态
- lint/typecheck 状态

如果某项没有执行,就说“未验证”。


最后这一句尤其重要:

没验证过的,就直说没验证。

“我没有运行集成测试”这句话,远比虚假的自信有用。


把实现和验证分开

对于重要的改动,不要让同一个工作流既负责产出结果,又负责给自己的结果盖章认证。

更强的模式是这样的:

agent 实现功能
        ↓
独立运行的测试命令
        ↓
CI 验证
        ↓
人工审查结果


对于风险更高的改动,还可以更进一步:

Agent A → 负责实现

Agent B → 对抗性审查

CI → 测试/构建/安全检查

人工 → 最终批准


关键在于独立性。

生成代码的那套系统,不应该成为你相信代码正确性的唯一来源。


CI 才是唯一事实来源

agent 发来的消息只能当作有用的背景参考。

而不是最终权威。

比如:

agent 说:

所有测试都通过了。

CI 说:

3 个集成测试失败了。

相信 CI。

这就是为什么即使 AI 写的代码越来越多,传统工程体系依然重要。

你仍然需要:

  • CI
  • 确定性测试
  • 构建检查
  • 类型检查
  • lint 检查
  • 安全扫描
  • 部署门禁

AI 不会取代这些体系。

反而会让它们变得更重要。


小心“已修复”这种说法

同样的原则也适用于 agent 的其他声明。

比如:

“这个 bug 已经修复了。”

是怎么验证的?

“构建没问题。”

运行的是哪条构建命令?

“没有破坏性变更(breaking changes)。”

做过哪些兼容性检查?

“这次迁移是安全的。”

有没有在贴近真实的数据上测过?

“这是安全的。”

实际运行过哪些安全检查?

AI agent 的语气可以显得无比笃定。

但笃定不是证据。


一份更好的完成报告

与其这样:

完成了。

一切正常,所有测试通过。


我更希望看到这样:

功能实现完成。

已执行的验证:

npm test
Exit code: 0
128 个测试通过
0 个失败
3 个跳过

npm run typecheck
Exit code: 0

npm run lint
Exit code: 0

集成测试未运行。

浏览器手动测试未执行。


这样的报告有用得多。

我清楚地知道哪些被验证过了。

哪些没有。


把“未验证”加进你的词汇表

AI 辅助开发最缺的一句话就是:

未验证。

agent 说下面这些话完全没有任何问题:

已实现,但未测试。

或者:

单元测试通过,集成测试未运行。

或者:

我无法验证这一点,因为所需的服务不可用。

这些回答都好过假装笃定。

好的工程实践不在于听起来自信。

而在于清楚自己手上到底有哪些证据。


我的一条简单规则

对于任何重要的 AI 生成改动:

永远不要轻信这句:

“能跑。”

而要认这句:

“这是我的验证过程。”

这一点差别,就能挡掉大量的虚假自信。


一份实用检查清单

在接受 agent 的“测试通过”消息之前,先问:

执行的是什么命令?

你应该知道确切的那条命令。

运行的是完整的相关测试套件吗?

而不是只跑了其中一个子集。

退出码是多少?

成功与否应当是可度量的。

有没有被跳过的测试?

被跳过的测试同样重要。

验证是在最后一次代码修改之后运行的吗?

而不是在最后一次编辑之前。

CI 确认过结果吗?

优先采用独立的验证。

我能查看输出吗?

证据应该随时可以调取。


写在最后

AI 编程 agent 生成代码的能力越来越强。

但随着它们越来越自主,开发者需要对一件事更加上心:

验证。

危险的工作流是这样的:

AI 写代码
↓
AI 说能跑
↓
人信了
↓
合并


更好的工作流是这样的:

AI 写代码
↓
AI 出示证据
↓
运行独立检查
↓
人工验证
↓
合并


因为:

“测试通过”这句话,并不是测试确实通过的证明。

它只是一个声明。

而在软件工程里,重要的声明都应该拿得出凭证。

原文:https://dev.to/robertadam987_/your-ai-coding-agent-says-tests-pass-but-did-it-actually-run-them-4684(作者 @robertadam987_)

发布评论
全部评论(0)