门禁这件事,就是定下「拦什么」的标准
一句话总结
测试门的本质不是频繁进行测试,而是事先商定在出现某种信号时如何阻止合并,并让机器代替做出判断。
##为什么需要这个
缺陷越晚发现越贵。IBM研究被广泛引用的水分损失开发阶段1、QA10、生产100以上。即使是相同的错误,在我的分支中发现的话30分钟就能结束,但在生产中发现的话,除了故障应对、热修复、反思、客户沟通外还会附加费用。门是试图在成本曲线左端发现的装置。
问题在于要做多少测试。测试金字塔的推荐比例是单位70/综合20/E2E10。如果变成倒置的反金字塔(冰淇淋棒),四个都会同时出现。E2E会变慢,反馈循环变长,玩家频繁,即使失败也很难找出原因,维护成本也会成指数级增长。测试变多了,但没有人相信结果的状态就是这样的。
怎么操作
大门分为三个部分。
第一,评判标准。覆盖率的目标是核心业务逻辑80%以上,总共60~80%,但不能忘记,比起100%覆盖率,具有有意义的assertion的测试更重要的原则。只按数字来做的测试只会让覆盖率报告看起来漂亮,而错误则会原封不动地通过。
第二,阻止策略。必须阻止与单元的整合。E2E只阻止主要流,其余留作观察。性能只有在超过临界值时才会阻止,安全扫描只阻止CRITICAL。混沌测试保持非阻止状态,只观察指标。全部阻止的话,人们会先学会绕过门槛的方法。
第三,强制分支。实际强制门禁的地方不是管道脚本,而是分支保护的required status checks。脚本只生成结果,阻止合并的权限由仓库设置提供。IaC方面也有同样的做法。Plan在PR中显示,Apply在merge后自动执行。
Playkey测试是吞噬门的信任的幕后黑手,需要单独处理。使用等待特定条件的显式等待,而不是固定的sleep,断开测试之间的依赖性,用 Mocking 或有限重试来包围网络,将日期等动态数据固定。重试必须有上限。无限重试不是稳定化,而是掩盖失败。即便如此,摇摆不定的测试也要放入隔离列表,防止合并,但要留下隔离的事实在报告中,以免被遗忘。
在现场相遇的样子
第一次打开大门时,一定会收到“现在很着急,因为这个原因不能出去”的请求。这时需要的不是例外批准程序,而是关闭大门的开关。另一个经常看到的场景是,为了修复失败的测试,而增加重试次数。虽然重试次数增加,但如果失败率保持不变,那么该测试已经不是信号,而是噪音。
要快才能守住大门
人们绕过闸口的最大原因不是因为规则严格,而是太慢。如果要等40分钟才能合并,开发者就会把小变化收集成一大块,一大块很难进行评论,也很难撤销。从闸口的目的是完全相反的角度来看,这不仅仅是简单的不便,而是设计失败。
获得速度的方法是确定的。
-
**只支付变更的部分。**如果是单轨仓库,就看哪个包裹发生了变化,只测试影响范围。即使是单个存储库,也没有理由把整个测试都转向只有文件变更的提交。
-
分阶段进行。 先把快一点的任务做完,几分钟内通知失败,慢一点的任务留到后面。如果前一步失败了,后面就完全不开始了,所以平均等待时间大大减少。
-
**并行运行。**将考试分成多个分支并同时执行。此时,如果考试之间共享状态,并行化就会迅速变成不稳定,因此,每个考试都要自己创造和清理自己的资源是前提。
-
缓存。 如果依赖性安装每次需要几分钟,那就先解决那个。比减少测试代码效果大得多。
也不要忘记计时。**记录管道各阶段所需的时间,如果有一天突然变慢,就可以找到原因。**如果没有这个记录,只会重复“最近CI变慢了”,没有人能回答从什么时候开始变慢。
最后,决定门的成败的一个文化条件是不要忽视红色管道。如果main被破坏了一天,后面出现的任何更改都无法知道是自己的错还是不是,门作为信号的功能就会完全丧失。需要达成一致,如果被破坏了,修复或恢复比其他任何工作都优先。因为恢复几乎总是最快的,所以即使还不清楚原因,先恢复main为绿色并调查也是正规做法。
##下次实习要做的事情
直接用Shell制作测试跑者和覆盖门、重试、隔离。即使失败也让跑者把剩下的全部回转到最后,展示整个画面。覆盖门在界限值上准确判断,有上限的重试,以及制作出数值和判断一致的JSON报告。