你有没有试过让 Agent"实现功能,顺便带上测试"?大概率会拿到这样一份结果:所有 service 层的单元测试,覆盖率 90%,一片绿。
但反过来做个实验——把 service 和 repository 之间的一个参数名改掉,再跑一遍测试——没有一条测试变红。
这个组合挺让人不舒服的:覆盖率 90% 和"改了代码测试不动"同时成立。测试确实在跑,也确实绿,只是绿的地方不在你改的地方。
最近知乎上一篇叫《vertical-tdd》的文章,把这件事挑明了。知乎这也是 AI 编程圈最近吵得最凶的话题之一:AI 时代的测试,到底在证明什么?
一、为什么 AI 写的测试,总是看起来特别健康
Agent 没偷懒,它只是选了一条最省力的路。
水平切,好批量产出:一次就能交出"所有 service 的测试";每一层又都能 mock 掉下一层——service 测试里 mock 掉 repository,controller 测试里 mock 掉 service——于是没有一条测试需要碰真实集成。知乎结果就是,每条测试只证明了一件事:我正确地调用了下一层的 mock。它没有证明用户能完成任何事,也没有证明两层真能拼在一起。改个参数名不红,因为测试从没让这两层握过手;覆盖率照样很高,因为它度量的只是"代码被执行过"。
《领域驱动设计》的 Eric Evans 有句话可以直接拿来当判据:代码是模型的表达,改变某段代码就改变了相应的模型。知乎反过来读——改了代码而测试不红,测试就没有在表达模型,它表达的是一堆 mock 之间的礼貌寒暄。

二、把单位换成"用户故事",是完全不同的世界
vertical-tdd 这套做法,核心不复杂:一条测试,对应一个用户故事。
这条测试从用户入口发起,穿过真实的 service、真实的 repository、真实的测试数据库,回到用户看得见的响应。知乎这样的测试,被叫作垂直切片(vertical slice)。
从命名就能一眼分辨:
test_export_service_returns_200,说的是实现细节;
test_user_exports_cargo_as_csv,说的是领域动作。
产品经理能读懂测试名,才说明你的测试度量的是"用户能不能把事办成"。mock 不是不能用,而是只能出现在系统边界:第三方 API、系统时间、随机数、外部消息队列。
那篇文章给了一个特别狠的判据:删掉所有 mock,测试还能跑吗?知乎跑不动,说明 mock 已经长进了你自己的模型,而不是留在边界上。
三、光写对测试还不够,"红"必须被看见
垂直切解决的是"测什么",AI 还有一个高发问题:省略"红一次"。
Agent 的常见操作是先写测试、紧接着把实现写出来、一次提交——测试从未真正失败过。知乎这样的测试很可能是照着实现反写的,而一个从没红过的测试,你无法证明它能捕获错误。
所以 vertical-tdd 要求红和绿落成两次可观察的状态:先写测试,运行,看它因为"功能未实现"而红;再写最小实现,运行,看它绿。知乎而且一次只让一条切片红——摊开三条切片一起写,每条实现一半,最后没有一条完整路径是绿的。

少了红那一次,TDD 就退化成给已有实现补一张合格证。这句话大概是最近对"AI 测试先行"最狠的一句批评。
四、丑话说在前面:这套方法的代价
它不是免费的:
慢。真实的层加真实的测试数据库,比 mock 版慢得多;
红了不告诉你哪层坏。它只说"用户这件事做不成",定位得自己往下挖。
所以有人宁愿要一堆毫秒级的单元测试:红一条就知道坏在哪个函数。垂直切片换来的是另一种安全网——单元测试测的是实现细节,改一层碎一片,碎多了谁也不敢动;垂直测试度量的是用户动作,改任何一层的回归都会立刻在这里显形。
这也是为什么我觉得本周社区这场架吵得有价值。前几天一份探索性评测给"强制 Agent 做 TDD"泼了冷水:TDD 没带来更好的设计或更高的变异测试得分,token 用量却可能增加到数倍(作者自己也承认样本很小,只能算探索)。知乎但仔细看评测暴露的问题——Agent 先写实现再补测试、跳过变红步骤、用实现本身的逻辑反写期望值——你会发现它批评的不是"测试不该写",而是"被仪式化的空心 TDD"。
两边真正的交集在这里:重要的不是红绿仪式执行得多严格,而是测试有没有真的在表达"用户能做什么"。
五、一份可以直接抄的清单
想试的话,建议按这 5 条来:
一条测试 = 一个用户故事:从用户入口到响应一条完整路径,不要批量产出每一层的测试;
mock 只留在边界:第三方 API、时间、随机数、消息队列。删掉 mock 跑不动的测试,先修它;
红必须是一次可观察的运行:先写测试跑一遍看红,再写实现跑一遍看绿,测试和实现分两次提交;
一次只让一条切片红:一条走完红、绿、整理,再碰下一条;
写实现的当下就写好:别用"先写烂,绿了再重构"安慰自己,AI 特别容易照着身边最脏的那段代码依样画瓢。
再说说适用人群:
新项目、中小型功能:最值得试,垂直切片成本最低、见效最直接;
老项目存量代码:垂直切未必切得动,先从最靠近用户入口的路径做起,老的部分该 mock 先 mock,别硬上;
连"用户动作"都说不清的需求:别急着写测试。社区现在的共识是先 grill——用需求澄清流程把边界问清楚,落盘成 spec,再谈切片。
六、接下来看什么
这波讨论还在升温。B 站上已经有人把 skills 的主流程逐段拆解成了教程,小红书连"/tdd:红绿重构"的帖子都直接管这套反馈循环叫"强得离谱"。哔哩哔哩小红书
就在今天(8 月 22 日),Matt Pocock 的 skills 仓库冲上 GitHub Trending 榜首,单日新增 3368 星,总星标 22.9 万(社区统计)。知乎另一套 Agentic 工程流 superpowers 的官方定位,是一套约束编程 Agent 的软件工程流程。哔哩哔哩它的星标已达 27.4 万,今天查 GitHub 官方接口已经超过 27.5 万。两者都把 TDD 放在流程核心,也都在回答同一个问题:怎么让 Agent 交付的东西可验证。

想持续跟进,看两个信号就够:一是有没有人用更大规模的实验,证明垂直切片在 Agent 场景下真的减少了回归——目前的支持多是实践文章,缺硬数据;二是变异测试工具会不会出现好用的 Agent 集成——那是客观验证"测试到底拦不拦得住错误"的尺子。
AI 时代,测试是你给自己留的最后一道防线:它是唯一能在 Agent 说"我做完了"的时候,告诉你到底做没做完的东西。别把它也外包成一张合格证。