Back to Blog
·1 min read

全绿的测试板,和零核心流程覆盖,可以长期同时为真

全绿的测试板,和零核心流程覆盖,可以长期同时为真。 发现的方式很平常,甚至有点难堪:我给自己立过一条规矩——每个 app 至少要有一个测试,启动它,把核心工作流从头走到尾。这次是这

全绿的测试板,和零核心流程覆盖,可以长期同时为真。

发现的方式很平常,甚至有点难堪:我给自己立过一条规矩——每个 app 至少要有一个测试,启动它,把核心工作流从头走到尾。这次是这条规矩先叫的:不是有测试挂了,而是根本不存在一个会去驱动核心流程的测试。这个 app 的主路径,从未被任何测试执行过,构建和周边检查全程绿灯。

为什么它能藏这么久:绿灯度量的是零件。单元测试绿、构建通过、周边检查绿,每一条都在证明"部分正确";而核心路径的缺失是一种缺席,缺席不会让任何东西变红——一个从不存在的测试永远不会失败。于是"全套绿"和"产品存在的那条理由路径从未被端到端跑过"互不打扰地共存着。

修法,顺序是承重的:

1. 先证明缺席,别急着写测试。在测试目标里搜核心流程的入口——那个控件、那条路径、那个终态,整个 app 存在的意义。没有任何测试会启动 app 并走到终态,就是同一个洞。先做这步,是因为它决定你接下来写的是"核心流程测试"还是"又一段组件检查"。 2. 再搭壳。先让一个真正会启动 app 的 UI 测试目标存在、跑起来,内容可以还是空的,但它必须出现在执行计数里。判据是输出里 "Executed N tests" 那一行,不是成功标记——带着 Executed 0 的成功,是一个关于"无"的结论,什么都没证明。 3. 最后才填真实流程:启动、做这个产品存在要做的那一件事、断言在用户看得见的终态上(那个控件翻转到了它该有的状态),而不是断言某个方法被调用过——界面对不对,后者区分不了。

顺序为什么不能换:先写断言再搭壳,你测的是测试自己;流程填完却不看执行数,一次全绿可能什么都没执行过。

一分钟自检:打开你的测试目标,只问一个问题——哪一个测试会启动这个 app、把核心流程走到它的终态?答不上来,你的绿和我这次抓到的,是同一种绿。

#build-log

Written by

Peter Zhang

Building local-first Mac & iOS productivity apps at Obelisk Club.