AI 手记AI 手记

把测试交给 AI 写,但把断言留给自己

3 分钟0 阅读

我有阵子很得意,让 AI 给代码补测试,效率惊人。

一个函数,喂给 AI,它唰唰唰生成十几个测试用例,正常路径、边界值、异常输入,覆盖得像模像样。跑一遍,全绿。我心想,测试这活儿以后可以外包给 AI 了。

直到有一次,那函数出了个真实 bug,线上炸了。我回头跑测试——还是全绿。AI 写的那十几个用例,一个都没触发这个 bug。

全绿,但没用

我盯着那批测试看,明白了问题。

AI 写的用例,覆盖的是「代码已经做了什么」。它读函数实现,针对每条分支生成输入,验证输出符合实现。听起来没毛病。但问题在于——测试该验证的是「代码应该做什么」,不是「代码现在在做什么」

如果代码本身有 bug,AI 会顺着 bug 的逻辑写测试,验证 bug 的行为「正确」,于是测试全绿,bug 被保护起来了。这种测试是给 bug 背书的测试,不是抓 bug 的测试。

我那次的真实 bug,AI 之所以没覆盖到,正是因为它照着有 bug 的实现写的用例,bug 行为被它当成了「预期行为」。

AI 擅长铺,不擅长定

想明白后我理清了分工。

AI 擅长铺测试代码——那些重复的、模式化的、写起来烦人的部分:构造各种输入、调用函数、处理边界、组织测试结构。这部分它快且全,交出去能省一大半时间。

但断言必须留给自己——「这个函数在什么输入下应该得到什么结果」,这个「应该」是业务语义,AI 推不出来,只能从你对需求的理解里来。你不确定「应该」,AI 就会拿「现状」当「应该」,写出保护 bug 的测试。

我现在的做法

让 AI 写测试,我改成两步:

第一步:我先用人话写下「这函数该满足什么」——几个关键断言,比如「输入空数组返回 0 不报错」「重复元素要去重」「超过上限要抛异常」。这是「应该」,我自己定,不交给 AI。

第二步:把这份「应该」连同代码一起给 AI,让它围绕这些断言铺完整的用例,补边界值、补异常路径。

这样产出的是「围绕正确语义」的测试,AI 负责把它铺满,我负责语义是对的。全绿的时候,绿的是「代码符合预期行为」,不是「代码符合自己的实现」。

一个反直觉的收尾

这次教训让我对「测试覆盖率」这个指标祛了魅。

AI 能轻松把覆盖率刷到很高——它太会铺用例了。但高覆盖率不等于有效测试,如果那些用例都在验证 bug 的现状,覆盖率 100% 也抓不出问题。

真正决定测试质量的,不是用例数量,是那些用例背后的「断言」对不对。而断言是 AI 替不了你的部分——它需要有人知道「代码到底该干什么」。

把铺代码的活交给 AI,把定断言的活留给自己。这是用 AI 写测试的正确姿势。外包可以,但「什么是对的」这事,外包不了。

相关阅读