翻译解读 · X @yaogangqiang 三连发 · 2026-09-14 → 09-16

AI 代码狂飙后,测试成了新瓶颈

Gangqiang Yao,Pi Agent contributor、研发团队负责人。他的团队一天上线 50 次、一天至少跑 300 轮测试。这个三连发系列用一线数据回答了一个 vibe coding 时代所有人都撞上的问题:代码产出提速 10 倍之后,为什么交付反而更慢了?

这篇文章回答的问题:AI 写代码飞快之后,测试怎么写才不碎、怎么跑才不贵?

这篇文章应该回答但没回答的问题:他的团队多大规模、投入了几个人维护这套测试基建——照抄之前你得先掂量这个。

3 条系列推文,9/14 → 9/16 三天连发,论证链完整
116K+系列累计浏览(73K + 23K + 19.5K),中文技术圈刷屏级
50 次/天作者团队真实上线频率,一天至少 300 轮 CI 测试
12 min阅读时长,含全套编译 + 工程解读 + 可落地清单

系列全貌:一条论证链

这不是三条孤立的技巧帖,是一套完整的论证:测试保不了质量(破)→ 但测试仍是地基,要写对(立)→ 写对了还不够快不够省,要工程化(用)。作者的终局预告是:接下来聊 AI 写的代码该怎么 review。

第一幕 · 9/14

质量悖论:vibe coding 没有让项目变好

「写代码一直是最容易的环节,AI 只是让最容易的环节更容易了。」测试从来不是高质量软件的关键——Quality is designed in, not tested in。

第二幕 · 9/15

怎么写测试:六条军规

测试行为不测试实现、BDD 先行、禁止 mock、E2E 优先、覆盖率看剩下那 10%、规则全部 lint 化。系列中最火的一条,73K 浏览。

第三幕 · 9/16

怎么跑测试:300 轮/天的降本工程

精准测试(文件级影响反查)、测试分级(核心路径高频跑)、Runner 调度(本地 runner 比 GitHub 托管便宜不少)。附两篇顶会论文。

第一幕:质量悖论

开篇立论,22.8K+ 浏览。他从两个现场观察切入,最后落到一句软件工程的老话上。

观察一:vibe coding 产出大量代码,大部分项目质量并没有提高。他甚至听到某创业公司的人说——

「我觉得可能人肉写写代码,稍微长期来看,速度更快,因为现在天天修 bug。」

观察二:很多人说「那你让 AI 写测试啊」。现实是,如果不做任何调教,AI 写出来的全都是充满 mock 的、测试实现细节的脆弱测试,而不是验证行为的测试。

更残酷的是:即使你教会了 AI 写对测试,照样不能保证软件的质量。因为——

测试从来不是高质量软件的关键。Quality is designed in, not tested in.

这句话化用自质量大师 W. Edwards Deming 的经典论断。测试只能证明缺陷存在,不能证明缺陷缺席;质量是在设计和需求澄清阶段注入的,不是在测试阶段补出来的。他的潜台词:天天修 bug 的团队,短板不在写代码,在需求澄清和验证这两环——AI 把写代码压到接近零之后,这两块短板彻底暴露了。

第二幕:写测试的六条军规

系列最火的一条(73K 浏览、268 赞)。前提明确:测试不是质量的关键,但它是基础。针对业务项目,怎么写才算写对——六条,每条都直指 AI 写测试的惯性毛病。

军规 1

测试行为,不测试实现

测「重复下单不会重复扣款」,不测「某个方法被调用了几次」。业务没变,重构一下测试就碎一地,那多半写错了。AI 特别容易写这种测试——因为它写完实现顺手照着实现生成测试。

军规 2

BDD 先行,场景即合同

先写验收场景再写代码,测试描述统一用 user 开头,Given / When / Then 三段式,用户和 PM 也能看懂。核心是防循环论证:别让 AI 写完代码,再照着自己的实现证明自己没错。

军规 3

禁止 mock

Redis、PostgreSQL 能用真的就用真的;外部系统不好接就注入 fake,但要校验 fake 和真实系统的契约。时间逻辑用 fake timer,别 sleep 几秒再祈祷。AI 真的太喜欢随手 mock 了。

军规 4

E2E 优先,宁可少而真

大部分测试从用户入口走到可见结果,外部依赖可以 fake,实在不合适再写其他测试。测试多了就分级 + 精准测试 + 定期完整跑。别改两行代码,等 CI 半天。

军规 5

覆盖率 90%,重点在剩下的 10%

分支覆盖率先定 90%,但重点是剩下的为什么没测——尤其是失败路径。别让 AI 为了凑数字再写一堆垃圾测试。数字好看但失败路径全裸奔,等于没测。

军规 6

规则全部 lint 化

前面的规则尽量都写成 lint——不靠人的自觉,不靠 code review 记性,靠工具强制。AI 写测试的反模式(mock 泛滥、测实现细节、凑覆盖率)都逃不过静态检查。

注意六条之间的咬合关系:1 和 2 解决「测什么」(行为契约),3 和 4 解决「怎么测」(真实依赖、走完整链路),5 和 6 解决「怎么守住」(覆盖失败路径 + 工具强制)。这是一套体系,不是六个tips。

第三幕:300 轮 CI 怎么跑得快、跑得省

前两条评论区被问爆的问题(@yetone 也问了):vibe coding 代码产出快了,测试慢、CI 贵的问题被放大。他的答案是一个工程组合拳,19.5K 浏览。

招式 1

精准测试:文件级影响反查

记录每个测试实际经过的代码,源码变更后反查会影响哪些测试。可以做文件级,也可以做函数级——他选文件级。函数级能少跑一些测试,但采集、分析和维护依赖的成本也不低;文件级会多选一些测试,但实现简单,整体省的时间更多。配置、依赖、初始化这类变更要单独处理(这类变更影响面是全局的)。Vitest 自带的「比较糙,效果有限」。

招式 2

测试分级:核心路径高频跑

按 BDD 场景描述分清哪些是核心业务路径。高频 CI 只跑三样:核心路径 + 新增测试 + 修改过的测试。其余测试有代码变更就每小时集中跑一轮。代价是部分非核心问题会晚一点被发现——能接受多长时间,看自己的业务。这是明确的工程取舍,不是免费午餐。

招式 3

Runner 调度:按负载分配机器

容易被忽略的一环。不同测试集对 CPU、内存、IO 的需求不一样,要看机器实际负载分配合适的机器、控制并发度——并发开大了,不一定更快。他们也用了本地 runner(自己配置好的机器),在他的场景里成本比 GitHub 托管 runner 低不少。

作者附赠的两篇论文(放评论区)

Ekstazi(ISSTA 2015 ACM SIGSOFT 杰出论文):论证为什么文件级选择虽然可能多跑一些测试,整体反而更划算。utexas.edu 论文页

Google TestSage:大规模 Web 服务如何结合运行时记录和静态分析,选择需要重跑的测试。UIUC Lingming Lab

好了,测试相关的分享先告一段落。接下来会逐步聊聊,为什么只靠测试还不足以保证软件质量,以及 AI 写的代码该怎么 review、重点看什么。

工程解读:这套方法论在测试版图里的位置

他的「E2E 优先 + 禁 mock」在教科书眼里是异端——但它恰好是对 vibe coding 时代的正确响应。理解了时代背景,争议就消失了。

流派主张代表适用前提
测试金字塔70% 单元 / 20% 集成 / 10% E2E,追求反馈快、定位准Google《Software Engineering at Google》人写代码、变更节奏可控、单元边界稳定
测试奖杯集成为主(Integration-heavy),单元只留给纯逻辑,E2E 少量冒烟Kent C. Dodds(Testing Trophy)Web 应用、重构频繁、追求抗重构
本系列立场E2E 优先 + 禁 mock + 精准测试补速度@yaogangqiang 实践AI 高频重写代码、行为契约比实现结构稳定得多

关键洞察:三个流派没有对错,只有前提不同。AI 时代最大的变化是实现结构的稳定性崩塌了——AI 一天能把你内部模块重构八遍,但业务行为(下单不重复扣款)几乎不变。测实现的测试跟着重构碎一地,测行为的测试纹丝不动。这就是「测试行为不测试实现」从老生常谈变成生存法则的原因。他用精准测试 + 分级补回了 E2E 慢的短板——Google 用金字塔避免的问题,他用「选着跑 + 分批跑」解决。

精准测试 DIY:Vitest 自带 vs 自建

他说 Vitest 自带的精准测试「比较糙,效果有限」。糙在哪,自建要补什么——这是 TypeScript 项目可以直接动手的部分。

Vitest 自带(vitest related / coverage)

  • vitest related [files]:基于模块依赖图(import 关系)反查关联测试
  • 只看静态依赖,看不到运行时真实执行路径——动态 dispatch、回调触发的代码覆盖不到
  • 依赖图是全量的,不知道「这次变更真的会影响那个测试吗」,宁可多跑也不会少跑
  • 胜在零成本,配 --changed 即可用,适合起步

自建文件级选择(他要的效果)

  • 跑测试时用 V8 coverage(--coverage)记录每个测试真实经过的文件集合,落盘成 map:testFile → [sourceFiles]
  • 源码变更后反查 map:改了 A.ts → 找出所有经过 A.ts 的测试,只跑它们
  • 维护成本:map 会过期,需要定期全量跑刷新;动态 import、monorepo 边界要特殊处理
  • 这正是 Ekstazi 的思路(论文里叫 class/file-level test selection),工程上完全可自建,几百行脚本起步

选型决策:什么团队该抄,什么团队别抄

他的数字(50 次部署/天)说明这不是玩具团队。抄之前先过一遍这个决策表。

直接抄

AI 写码占比高 + SaaS/To C 业务 + TypeScript 栈 + 部署频繁。六军规全部适用,精准测试从 vitest related 起步,量大再自建 coverage map。

抄一半

有强合规/支付/医疗场景:军规 1/2/5 照抄,但「禁止 mock」要放宽——监管环境里外部依赖本来就要挡;「每小时批量跑」的延迟容忍也可能过不了审计。

先别抄

部署频率一周一次以内、CI 从没排过队:精准测试和分级是给「跑不动」的团队准备的,你的瓶颈不在这,先把军规 1/2 写进 AI 的系统提示词更划算。

他没说的三件事(压力测试)

① Flaky 治理缺席。E2E 优先的团队,头号杀手是 flaky test(偶发失败)。他一个字没提——而这一课的学费往往比精准测试还贵(重试策略、隔离、检疫区)。② 团队规模未披露。一天 50 次部署、300 轮测试背后,大概率有专人维护测试基建。一人团队照抄「自建精准测试」,可能维护 map 的时间比省下的 CI 时间还多。③ 调教成本被隐藏。「教会 AI 写对测试」的规则维护(prompt、lint 规则、review 惯例)是持续投入,不是一次性配置。

苏格拉底对话:让 AI 写测试,为什么总是碎

一个 vibe coding 重度用户和这个系列的碰撞。

学生:我让 AI 给我的模块写测试,覆盖率一下到 95%,看着挺美的。但每次小重构,测试碎一片,我现在花在修测试上的时间比写功能还多。是我的用法有问题吗?

问一下:碎掉的那些测试,断言的是什么?

学生:大多是「这个函数被调用了两次」「返回的数组长度是 3」这种。

那你已经踩中第一条军规了:测试行为,不测试实现。「函数被调用两次」是实现细节,「重复下单不会重复扣款」才是行为。判据就一条——业务没变,重构后测试碎了,那多半是写错了,不是重构错了。

学生:可这些测试是 AI 写的,它照着我的实现生成的,能不贴着实现走吗?

这就是最深的坑:AI 写完代码再照着自己的实现写测试,是用实现证明实现,循环论证。破法是 BDD——先写验收场景(Given/When/Then,user 开头),让场景先行,代码后行。测试和实现必须来自不同的源头,互相才有约束力。

学生:明白了,那我让 AI 先写场景再写代码。但它写测试还是喜欢一通 mock,mock 了个假的 Redis,测试全绿,上线照样炸。

mock 的 Redis 测的是「你的代码以为 Redis 是什么样」,不是「Redis 真的是什么样」。所以第三条军规:能用真的就用真的,不好接就注入 fake——但 fake 要校验和真实系统的契约。AI 喜欢随手 mock,因为 mock 让测试最容易变绿,而变绿是它被奖励的方向。

学生:那我把依赖全换成真的,测试又慢得没法忍,CI 一跑四十分钟,改一行等半天。

到第三幕了:速度问题不是靠少测解决,是靠选着跑解决。记录每个测试真实经过的文件,改了哪个文件就只跑经过它的测试;核心路径每次跑,其余每小时批量跑;再看 runner 的负载分配。他 300 轮/天就是这么活的。

学生:可这些基建,我一个人做项目,值得吗?

好问题,也是这个系列没回答的。一个人项目的答案可能是:军规全要(它们是写给 AI 的提示词),基建缓建(vitest related 一行配置先跑着)。等你 CI 开始排队,再回来抄第三幕。工具永远跟着痛走,不跟着推文走。

个性化洞察:这套东西怎么落到你手上

基于你的背景定制:QA 出身、TypeScript/Node 栈、独立开发多个 AI 产品、日常重度 vibe coding。

洞察 1

六军规直接变成你的 AI 系统提示词

你为什么相关:你的项目全是 AI 写码,军规针对的就是 AI 的三个惯性病(测实现、随手 mock、凑覆盖率)。怎么做:把「测试行为不测实现 / 禁 mock 用真实依赖或契约 fake / BDD Given-When-Then 先行」三条写进各项目的 CLAUDE.md 测试规范段,一次配置长期生效——这本身就是军规 6 的 lint 化思路。

洞察 2

vitest related 是你今天就能白嫖的精准测试

你为什么相关:TS/Node 栈,symphony、happyread 这些项目改一行全量跑 CI 的痛你会越来越频繁地遇到。怎么做:CI 里把 `vitest related $(git diff --name-only HEAD~1)` 接进去,零基建拿到文件级选择 80% 的收益;等测试集上千再考虑自建 coverage map。

洞察 3

BDD 场景是你一人团队的「PM 文档」

你为什么相关:独立开发没有 PM 帮你澄清需求,需求澄清恰恰是 vibe coding 时代最大的质量短板(第一幕的结论)。怎么做:新功能开工前先让 AI 只产出 Given/When/Then 场景清单,你审场景而不是审代码——场景就是需求文档,还能直接转测试。这一步把「需求澄清」和「测试设计」合并成了一次劳动。

洞察 4

盯住作者的下一条:AI 代码 review

你为什么相关:系列终局预告「为什么只靠测试不足 + AI 代码该怎么 review」,和你 QA 背景 + AI 工程的双重视角完全同频,大概率还会带出 Agent/harness 工程实践(他的主业)。怎么做:关注 @yaogangqiang,或等下一条出来再让我跑一次同样的解读流水线。

精选评论

主推文 11 条回复中的高价值增量。

@yaogangqiang(作者补充,5h):两篇精准测试论文的出处——Ekstazi 获 ISSTA 2015 ACM SIGSOFT 杰出论文奖,解释「为什么文件级选择虽然可能多跑一些测试,整体反而更划算」;Google TestSage 讲大规模 Web 服务如何结合运行时记录和静态分析选择需要重跑的测试。把「个人经验」锚到了学术文献上,这是整条推文可信度的关键一跃。

@YMaxwellHayes:「一天 300 轮测试的量级,我们内部的经验是三件事最见效:按变更文件反查影响的测试子集只跑相关的、把外部依赖全部替换成本地假实现、慢测试单独分层每天跑一次。Vibe coding 之后代码量涨得快,测试的分层比测试的数量更重要。」——独立信源交叉验证了作者的方法论,且最后一句是全系列最好的注脚。