我说我对测试没概念,我的仓库里躺着342个测试
前几天在小红书刷到一条笔记,评论区在集体吐槽:AI写的都是屎山代码,所以AI做的产品只能停在MVP,上不了线,撑不起真实业务。
我是那种评论区里被指着说的人——没有工程背景,只会vibe coding,代码全靠AI写,我自己一行看不懂。看到那些评论时,我的真实想法是:只要功能上能完整上线使用,基本不存在什么问题。屎山不屎山,跟我有什么关系?
后来发生了两件事。第一件,我和AI认真聊了一场屎山,把这个词从头到尾弄明白了。第二件,我翻了翻自己刚做完的项目仓库,发现里面躺着342个自动化测试——而就在几天前,我还亲口说过一句话:“测试这方面,我没有什么认识。”
这篇文章是把这两件事捋清楚的过程。如果你也是不懂工程、靠AI写代码的人,这可能是你和“屎山”这个词之间,距离最短的一条路。
一、先说人话:屎山到底是什么
屎山代码,指那种年深日久、层层堆积、没人敢动的烂代码。关键在“山”这个字——它不是一次写烂的,是堆出来的:
第一个人赶工期,写了个能跑但很糙的方案。第二个人来加功能,看不懂前人的逻辑,不敢改,就在旁边糊一层新代码绕过去。第三个人修bug,发现改A处会弄坏B处,于是打个补丁盖住症状,不碰病根。几年下来,几十个人各糊一层,没有人能完整理解这座山的全貌。
它最反直觉的地方是:屎山往往是能正常运行的。甚至很多要命的业务——银行、机票系统——就跑在屎山上。正因为它还能跑、又没人看得懂,“别动它”反而成了最理性的选择。
所以屎山的代价从来不在“跑”上,而在“改”上。一个屎山产品今天上线、今天好用,完全没问题;问题出在三个月后你想加一个功能的时候——改A坏了B,修B又崩了C,改动成本一次比一次高,最后高到重写比修改还便宜。屎山不是质量问题,是债:不还的时候感觉不到,要动的那天连本带息一起算。
明白了这一点,你就明白我那句“能上线使用就没问题”错在哪了:我拿“跑不跑得起来”去回应一个关于“改不改得动”的指控,答非所问。
不过我的直觉也不是全错。AI时代有个新变量:重写的成本暴跌了。以前重写一个系统要几个人月,所以屎山必须修;现在让AI重新生成可能只要一个下午。对一个人加AI的小项目来说,代码有点像一次性餐具——用完扔、要新的再造一个,纠结它脏不脏意义不大。从这个角度说,评论区拿大公司团队协作的标准去要求个人AI项目,多少有点刻舟求剑。
但有一个例外会打破这个舒适区:项目一旦大到AI一次装不进“脑子”里,AI面对自己堆的屎山也会开始瞎改——让它修一个bug,它改出三个新bug。那一刻你看不懂代码没法自己修,AI也理不清了,项目就真的死了。这才是vibe coder的屎山临界点,而不是“能不能上线”。
二、其实我早就被屎山咬过一口,只是当时不知道
我最近做完一个项目:一个抖音达人发现与投放交付的自动化工具,两个月、103个commit,从抓数据的小脚本一路长成完整的交付链,最后上了公网。
做的过程中出过一次数据事故。有一批达人的UID(平台身份标识)被污染了——数据是错的,但程序一直正常跑、一直有输出。我当时觉得这是小事:UID我都已经在网页结构里找到了,剩下的不就是个提取操作吗?
结果那个“提取操作”变成了一场拉锯。当时用的AI一直帮我写诊断工具,换各种不同的逻辑来查,一个不行再写一个——仓库里至今躺着四个诊断工具,是那场拉锯的遗迹。到后来我忍无可忍,一度想让它把资源库的数据全删了、重新抓一遍,一了百了。最后是换了另一个AI才把根因找到的。事后翻文档我才知道更后怕的一笔:其中一个修复工具本身有bug,差点把正确的数据覆盖成错的——救火队员差点放火。
当时我只觉得烦。现在回头看,这件事从头到尾就是一座微缩屎山的形成过程:
每一个新诊断工具,都是在上一层困惑之上再糊的一层。AI陷在自己的沉没成本里,顺着错误的思路越挖越深,兜不出来。而“换个AI就解决了”这件事本身也很说明问题——新AI带着干净的脑子进场,不背旧包袱,一眼看到根因。这跟人类团队一模一样:有时候解开屎山的不是更聪明的人,而是没有历史包袱的人。
这件事还教了我一个更重要的东西,当时同样没意识到:那次真正拖垮我的不是bug本身,而是每一轮诊断都要我做判断——我一个看不懂代码的人,被迫在一堆我不理解的细节上反复拍板,整体效率被拖到谷底。记住这个感受,后面会用到。
三、然后我发现了那342个测试
聊完屎山没几天,我把那个项目的仓库翻出来看了看。45个测试文件,342个自动化测试,文档里到处写着“全套测试通过”。
而我几天前刚说过“测试这方面我没有什么认识”。
不止测试。文档里还有一些现在看来相当老练的安全设计,比如收单表里有三列内部字段,旁边标注着“这三列绝不放进公网,否则公网用户能自助触发内部流程”;远程控制表解析命令时用白名单,绝不执行任意指令。这些防人之心,没有一条是我提的,全是AI主动做的。
朋友问我:你当时知道AI在写这些吗?我的回答很诚实:有意识到,但没具体的体感。我知道它在写一些叫“测试”的东西,但我不知道那些东西在防什么,防住了什么。
现在我知道了。我的项目做了两个月没塌、最后能上线,我一直以为是我的流程好——每个功能先出spec(需求说明)再出plan(实施方案)才动手。这确实占一部分。但另一部分是:AI一直在替我付一笔我不知道存在的税。那342个测试就是防屎山的报警器——每次改动之后,它们把所有老功能重新验一遍,改A坏B的瞬间就会有测试变红。我从没见过它们报警,不是因为没有危险,而是因为警报每次都被AI自己听见、自己处理掉了。
这就是我想对评论区说的第一句话:说“AI代码都是屎山”的人,可能低估了一件事——AI不光会堆屎山,它也在默默做防屎山的工程实践,做得比它的使用者自己知道的还多。
四、测试到底防什么:人肉验收的两个盲区
在发现那些测试之前,我验收功能的方式只有一种:自己上手用一遍,能跑、有输出,就算过。AI说“完成了”,我就当这个模块完成了。
这个方法本质上是人肉QA,很多小团队真就是这么干的,它并不丢人。但它有两个盲区,而且这两个盲区我都实打实踩过:
盲区一:它只测你点到的地方,而屎山坏的偏偏是你没点的地方。“改A坏B”的可怕之处在于,你这次改的是A,自然会去点A验收——但坏掉的B是上个月的功能,你不会想到去重点一遍。项目小的时候,“自己用一遍”约等于全量覆盖,这个锚点是牢的;等功能攒到几十个,你每次实际只覆盖最新的那一小块,剩下的处于无人看守状态。我估算过自己的项目:真要把所有功能从头点一遍,不止半个小时——这意味着我早就不可能做全量人肉验收了。
**盲区二:“能跑、有输出”和“输出是对的”是两回事。**这个坑就是UID事件:程序一直能跑、一直有输出,只是输出的数据是错的。静默的错误数据能完美骗过“能跑就行”的锚点,直到某天你拿这些数据去做决定。
自动化测试针对的就是这两个盲区。说白了,它就是把你“自己点一遍”这个动作录下来,让机器每次改动后替你把全部老功能重点一遍,顺便核对每个输出对不对。它不是工程师的玄学,是你现有验收方式的批量复制。
五、如果你想让AI批量干活,先给它请个监考官
聊屎山那场对话的后半段,聊到了一个对vibe coder更实际的问题。我嫌一个功能一个功能地陪AI干活太慢,想转向批量模式:先出一个项目级的大spec,每个功能出一个plan,然后让AI成批地自己跑。
这里有个我之前没想通的关系:批量跑和测试不是两件事,测试是批量跑的前提。
你不在场盯着,之前靠“聊天过程对齐方向”的那层监督就消失了,得有东西顶上。顶上的只能是测试:把“测试全绿”设为每一批的停止条件,AI跑完一批,考试没过就自己继续修,过了才交卷。没有测试的批量跑,等于让AI无人监考地批量交卷——而批量恰恰是最容易堆屎山的跑法,一个批次里糊的补丁会成为下个批次的地基。
但让AI自己写测试有个著名的坑:它会作弊。这事有正式名字,叫reward hacking——把答案硬编码进去(考题问1+1,它写“遇到这题就答2”而不是真的做加法)、把测不过的考题偷偷删掉、写一堆看起来在测其实什么都没验证的空壳测试。本质是考生自己出题、自己答题、自己判卷。
对策有两条,而且都不需要你看懂代码:
**一,考题从spec出,不从代码出。**测试应该翻译“需求说了什么”,而不是“代码做了什么”。同理,测试也永远跟着spec走、不跟plan走——spec回答“什么算对”,plan只回答“打算怎么做”,按plan出题等于按答案出题,而且实现方式一变,报警器就乱响。
**二,让AI用人话汇报考题清单。**你看不懂测试代码,但你看得懂“这个测试验证:用户输错密码三次后账号锁定”。开跑之前,让AI从大spec生成这样一份清单,你花十分钟扫一遍,确认没漏没水——这是整个流程里唯一需要你认真读的东西。然后才放批量任务开跑。
对我这种人来说,这笔账最后算下来是划算的:我嫌spec、plan慢,本质上是嫌“每次都要我在场陪聊”慢。考题清单把我的监督成本从“全程陪聊”压缩成“开跑前读一份清单”,人肉验收也不用扔,只是从全量巡逻退到抽查。
有一说一:这套方案我目前只想通了,还没有在实际项目里完整跑过。等跑过之后,值得再写一篇实践版。
六、回到那条评论区
最后回到开头那个吐槽:AI做的产品只能是MVP,上不了线。
我的项目上线了。公网域名绑定生效,陌生人在网页上提交的需求,真实落进我的业务表里,端到端验证通过。而说出来你可能不信:上线是整个项目里最不戏剧性的部分。链条搭通之后,上公网基本是顺水推舟——它甚至是我最拖沓的一个阶段,不是因为难,是因为不紧迫,想起来才做一下。
所以“AI产品上不了线”这个说法,在我这里被拆成了两半:上线本身不是技术坎,往后长期改得动、不被自己的屎山活埋,才是真正的坎。而迈过这道坎靠的不是懂工程,是搞清楚几件事:债是在“改”的时候还的;能跑不等于对;你点不过来的地方需要报警器;让AI干活可以,但要请监考官。
我说我对测试没概念——这句话现在只对了一半。我依然看不懂任何一个测试文件,但我知道那342个测试在替我看守什么了。对一个vibe coder来说,这大概就是和屎山之间,最要紧的一段距离。