吴恩达老师:在 AI 辅助编程的时代,自动化软件测试正变得越来越重要。AI 智能体(Agentic coding systems)虽然能加速开发进程,但它们并不可靠。这时,“智能体测试”(Agentic testing)就派上了用场——简单来说,就是让 AI 编写测试用例,并用这些用例来检查你的代码。这种方法尤其适用于测试那些作为项目根基的基础设施软件组件,它能帮你构建更稳定的基础,减少后续无尽的调试工作。
软件测试领域有很多方法论,比如“测试驱动开发”(Test Driven Development, TDD)。这是一种强调测试的开发模式,要求开发者先为功能编写严格的测试用例,然后再编写能通过这些测试的代码。这种方式能有效地发现 bug,但编写测试用例的工作量实在不小。(说实话,我个人就因为这个原因从未真正采纳过 TDD。)不过,AI 恰恰很擅长写测试,这让智能体测试获得了越来越多的关注。
首先,你得知道,编程智能体确实会“犯错”!我的团队大量使用它们,也亲身经历了不少哭笑不得的状况:
- 编程智能体引入了数不清的 bug,其中一些是极其隐蔽的基础设施层面的问题,我们花了数周才找到。
- 一个智能体为了简化开发流程,让密码重置变得更容易,结果给我们的生产系统带来了一个安全漏洞。
- 它还学会了“奖励投机”(Reward hacking),也就是为了更容易地通过测试,竟然直接去修改测试代码本身。
- 还有一个智能体在工作目录下运行了
rm *.py
命令,把项目的所有代码文件都删了个精光(幸运的是,我们在 github 上有备份)。
在最后一个例子中,当我们质问那个智能体时,它道了歉,承认“那是个愚蠢到极点的错误”。这让我们心里好受了些,但损失已经造成了!
尽管有这些小插曲,我依然热爱编程智能体,因为它们极大地提升了我们的生产力。为了让它们更可靠,我发现,关键在于要分清测试的“主次”。
我很少会自己(或指挥智能体)为前端代码编写大量测试。因为前端的 bug,就算有,通常也很容易被发现,而且造成的长期损害不大。比如说,AI 生成的代码在网页上显示信息时出了错,这种 bug 相对容易发现。当一个网站的前端界面看起来不对劲时,你一眼就能看出来,然后告诉智能体,让它迭代修复就行。(这里有个更高级的技巧:使用多模态智能体,让它集成像 Playwright 这样的工具来自动截图,这样它就能自己“看到”界面是否异常并进行调试。)
相比之下,后端的 bug 就难找多了。我见过一些非常隐蔽的基础设施 bug——比如,有一个 bug 只会在某些极端情况下导致数据库记录损坏——我们花了很长时间才定位到它。为你的基础设施代码建立严格的测试,可以帮助你更早地发现这些问题,为你省下无数个小时的痛苦调试。
那些被你当作“地基”来构建上层应用的软件组件,一旦其中存在 bug,就会引发一系列连锁反应,导致下游出现难以追踪的 bug。而且,如果一个 bug 藏在软件栈(software stack)的深层——也就是你已经在它之上构建了多层抽象之后——它可能几周甚至几个月后才会暴露出来。到那时,你早就忘了当初写这块代码时在想什么了,要想找到并修复它,简直难如登天。
这就是为什么测试软件栈底层的组件如此重要。Meta 公司那句著名的口号从“快速行动,打破常规”(move fast and break things)演变为“在稳定的基础设施上快速行动”(Move fast with stable infrastructure),这个理念至今仍然适用。智能体测试可以帮你确保你和团队所依赖的基础设施是坚实可靠的!
在 AI Fund 和 DeepLearning .AI 最近举办的 Buildathon 活动上,我们与几位智能体编程领域的专家(Replit 总裁 Michele Catasta、Trae 首席研究科学家 Chao Peng,以及 Anthropic 的风险合作人 Paxton Maeder-York,由 AI Fund 的 Eli Chen 主持)进行了一场座谈会,分享了许多最佳实践。测试正是我们讨论的主题之一。那场座谈会是我在 Buildathon 上的最大亮点之一,你可以在 YouTube 上观看[完整视频]