一个AI编程助手拿到需求,写完实现,顺手把测试数据、夹具、测试用例也一并生成。跑一遍,全绿。这算交付完成了吗?

有人把这个问题拆开看之后,发现了一个不太舒服的结论:全绿可能只证明了一件事——这套代码在自己定义的世界里是自洽的。

打开网易新闻 查看精彩图片

一个从物理学家那里借来的念头

很多年前,有人和一位前同事聊过很多关于AI的话题。对方是理论物理学家,喜欢往复杂问题里钻,那会儿正好是AlphaGo和Leela Chess的时期。他们聊决策、聊世界模型,也聊意识。

其中一句话留了下来:一个决策只有相对于某个世界模型才有意义。

这句话当时和软件测试没有任何关系。直到编程智能体开始自己写实现、写夹具、写测试,它突然变得非常实用。

测试数据不是输入,是"世界"的一部分

智能体一个需求,它会依次产出:实现、夹具、测试。整个过程顺畅,结果全绿。

但如果它在最开始就理解错了需求呢?

实现遵循的是解释A,夹具代表的是解释A,预期值建立在解释A之上,最后测试证明的是——解释A内部自洽。没有任何环节互相矛盾,系统仍然可以是错的。

这就是重新理解测试数据的起点。测试数据不只是执行一次测试所需要的输入,它定义了实现必须在其间表现的那部分世界。

对一个孤立的小函数来说,这个区别可能无关紧要。但对一个有状态、有关系、有存量数据、跨多个系统、还带着一堆没人完全记得的规则的业务流程来说,区别很大。

实现不该定义那个证明它正确的世界

让智能体生成测试数据本身没有问题。一个能力足够的智能体可以写Python脚本、执行它、造出质量很高的数据。

有人正是用这一点提出反驳:聪明的智能体可以先写生成代码再执行。

这个说法成立。代码还是模型,并不是关键。关键在于信息从哪里来

理想情况下,构建测试世界的智能体应该拿到这些东西:

  • 规格说明
  • 数据结构定义
  • 领域约束
  • 契约
  • 来自真实环境的相关信息

但不应该拿到它之后要评判的那份实现。

否则就存在一条捷径:智能体可以生成贴合实现实际行为的数据,而不是用数据去挑战实现本该有的行为。它甚至不需要有意识地这么做,同一个假设会从实现悄悄挪到夹具,再挪到预期值。结果是自洽的,也是错的。

为什么更倾向模型而不是生成代码

生成的代码可以工作。但审阅任意一段夹具代码时,必须同时理解两件事:它试图创造的是哪个世界,以及代码是怎么创造出来的。

把这两个问题分开会更好。用模型驱动的方式,可以直接看世界本身:

  • 实体
  • 关系
  • 基数
  • 允许的取值
  • 范围
  • 分布
  • 外键
  • 复合键
  • 预期

引擎负责持有这些东西,人看的是世界长什么样,而不是一段代码怎么把世界拼出来。当实现和测试由同一个理解偏差驱动时,全绿就不再是证据,只是回声。