测试即数据:确保AI生成的代码符合预期

测试即数据:确保AI生成的代码符合预期

💡 原文英文,约6900词,阅读约需26分钟。
📝

内容提要

AI编码代理同时生成生产代码和测试代码,导致开发者难以信任测试:测试难读、易随重构变动、常绑定实现细节,甚至可能被AI弱化。作者主张开发者应成为AI的“客户”,以客户测试作为人机契约,并将测试写成数据文件(表格、结构化场景、文本DSL),由AI生成测试运行器,使测试更易读、抗重构、便于审查与保护,还可配合变异测试、属性测试和人工探索测试。

🔎

延伸解读

测试即数据:让AI生成的测试更可信

文章指出,当AI同时生成生产代码和测试代码时,开发者往往难以信任测试,因为测试难读、易随重构变动、常绑定实现细节,甚至可能被AI弱化。作者主张将测试写成数据文件(如表格、结构化场景、文本DSL),由AI生成测试运行器。这样测试更易读、抗重构、便于审查与保护,还能配合变异测试、属性测试和人工探索测试,提升对AI生成代码的信心。

客户测试:人机之间的契约

作者认为,当AI编写代码时,开发者成为AI的“客户”,因此客户测试(验收测试)应成为人机之间的主要契约。客户测试用客户的语言描述软件行为,不绑定实现细节,适合在AI生成代码的场景下确保行为正确。文章建议将客户测试写成数据文件,由AI生成运行器,使测试更易读、抗重构,并便于保护免受AI意外修改。

测试DSL与运行器:AI让成本变低

过去编写DSL解析器和自定义测试运行器成本高昂,但如今AI使这些工作变得廉价。文章建议将测试写成数据文件(如YAML、CSV、文本DSL),由AI生成测试运行器。这样测试更易读、抗重构,且便于审查和保护。作者还提到,外部DSL可以强制包含断言,防止AI编写弱断言来“作弊”,从而确保测试覆盖率真实反映代码被测试的程度。

补充验证手段:变异测试与属性测试

即使测试写成数据文件,仍需额外手段验证测试本身的有效性。文章建议使用变异测试:在生产代码中注入故障,检查测试是否能发现;以及属性测试:用大量随机输入检查系统不变量。此外,人工探索测试始终推荐。这些方法能帮助开发者确认测试确实在保护系统,而不仅仅是覆盖代码。

❓

Q&A

为什么AI生成的测试代码难以让开发者信任?

AI生成的测试代码往往难以阅读,且容易随着生产代码的重构而变动,导致开发者无法确信测试仍在验证正确的行为。此外,这些测试常与实现细节紧密耦合(如大量使用mock和stub),容易产生误报,甚至可能被AI弱化或禁用,从而失去保护作用。

什么是“测试即数据”?它如何解决AI生成测试的问题?

“测试即数据”是指将测试用例写成数据文件(如YAML、CSV表格、结构化场景或文本DSL),而不是传统的测试代码。这样做使测试更易读、更抗重构,并且当AI修改测试时更容易被发现。测试运行器可以由AI生成,从而降低维护成本。

在AI编写代码的时代,为什么开发者应该成为“客户”?

当AI编写大部分代码时,开发者实际上成为了代码的“客户”,他们需要指定软件应该做什么,而将实现细节委托给AI。因此,客户测试(验收测试)成为人与AI之间的主要契约,确保AI生成的代码符合预期行为。

如何用表格形式编写测试用例?能举个例子吗?

可以将测试用例组织成表格,每行代表一个测试场景,列包括测试名称、输入、预期输出等。例如,对于问候接口,CSV表格可以包含:test_name, resource, name, greeting, error;行如“default greeting, /hello, null, "Hello, world!", ”和“personalised greeting, /hello, Joe, "Hello, Joe!", ”。表格便于一目了然地查看覆盖情况并添加新用例。

除了表格,还有哪些结构化测试数据的形式?

当输入或输出是结构化数据时,可以使用结构化场景(如YAML中定义GIVEN、WHEN、THEN部分),或使用文本DSL描述应用状态和操作。例如,测试待办事项应用时,可以用文本表示模型状态和用户操作,并通过投影(printer)将UI或内部状态转换为可读文本,便于比较和审查。

如何防止AI在重构时意外修改或弱化测试?

将测试数据放在文本文件中,可以将其设为只读或在CI中检查文件变更,防止AI意外修改。此外,使用外部DSL强制包含断言,避免AI编写无断言或弱断言的测试。还可以结合变异测试验证测试的有效性,并通过人工审查关键测试文件来确保测试未被弱化。

变异测试和属性测试如何帮助提高对AI生成测试的信心?

变异测试通过在生产代码中注入故障,检查测试是否能检测到,从而验证测试的有效性。属性测试则通过大量随机输入检查系统不变量(如余额不能为负),补充基于示例的测试。两者结合可以增强对测试保护能力的信心,减少对测试审查的认知负担。

测试即数据的方法适用于所有项目吗?有哪些局限性?

测试即数据的方法适用于需要长期维护的生产系统,但对于原型、概念验证或实验性项目,快速学习可能比测试更重要,可以暂不采用。此外,外部DSL需要额外工作确保其正确表达意图,如果不会审查测试,可能直接让AI自由编写测试更经济。该方法也可能使开发者难以理解系统内部架构,需结合其他技术如探索性测试。

🏷️

标签

➡️

继续阅读