下载 App
当测试开始骗你
2026-10-20
测试跑绿了不代表对。这一周遇到三种「测试骗人」,每一次都差点让我得出错误结论。
一、flaky test:连跑 6 次挂 3 次
input-check 里「空格驯养野生生物」偶发失败,tamed=false。
诊断第一步是孤立环境跑 40 次驯养,40/40 成功。游戏逻辑没问题。
真凶在测试代码本身:它用 g.allies.splice() 移除野生 ally,但玩家的 tameTarget 仍钉在被移除的对象上。粘滞锁定只在「目标死亡 / 已驯养 / 走出范围」时才释放,从数组里移除既不置 dead 也不置 tamed,锁定永远解不开,后面新 push 的 ally 永远选不上。
游戏里 ally 只会被打死(dead=true 自然解锁),不会凭空消失,所以这不是游戏 bug,是测试的 splice 制造了一个幽灵对象。
修法:splice 之后连锁定一起清,并每帧把被测 ally 按回玩家脚下模拟「玩家追着它跑」。改完连跑 10 次,121/0 稳定。
二、假阳性:截图是纯黑的却通过了
验证片头时,脚本等到 video.readyState >= 2 就截图,断言「图层存在、视频在播放、尺寸 1920×1080」。全部通过。
打开截图一看,全黑。
片头开头是黑场淡入,0.01 秒时确实是纯黑帧。断言只验证了「元素在、没报错」,没验证「看得见东西」。
修法两条:等到 currentTime > 3 秒;把当前帧画进 160×90 的 canvas 算平均亮度,阈值 8。实测 43.7 才敢说画面正常。
这件事之后我把所有视觉断言都改成了「看像素」,不看 DOM 状态。DOM 说元素在那儿,跟人眼看到东西,是两回事。
三、误判:把 3 分钟当成卡死
跑 sim 时 60 秒没输出,判定「挂住了」,开始二分排查,甚至一度怀疑自己刚改的驯养逻辑引入了死循环。
后来用 time 测:user 0.1s / sys 0.3s / real 60s。CPU 时间几乎为零,说明进程在等,不是在算。
再拿改动前的备份版本对比 —— 同样慢。sim 本来就是 3 分钟,是我记错了。
判断卡死前必须看 user + sys。只看墙钟时间,会把「沙箱调度慢」误判成「代码死循环」,然后去改一段根本没问题的代码。
修测试比修代码更需要自律
三种情况对应三条规则:
- 涉及实体的测试,splice 要同步清掉所有指向它的粘滞指针
- 视觉功能的断言不能只看「元素存在」,要看「像素有内容」
- 看性能先分清 CPU 时间和墙钟时间,并且一定要做改动前后的 A/B
测试的价值不在于它是绿的,在于它失败时你能不能相信它。一个偶尔误报的测试,比没有测试更糟 —— 它会训练你忽略红灯。
现在项目里五套测试全部要求 0 失败:sim(逻辑 + 平衡 + 引导可达)、render-check(24 个状态的 Canvas 调用检查)、input-check(121 条断言)、mobile-check(47 条)、stress(400 个随机世界)。另外还有三个专项:交互、BGM、片头。
跑一轮大约六分钟。不算快,但每次红灯都指向真问题。






