谷歌如何处理不稳定的测试用例!

乔梁 | 2022-03-21

不稳定是自动化测试的主要挑战之一

在谷歌,我们不断运行大量测试来验证我们提交的代码。从开发人员到项目经理,每个人都依赖这些测试的结果,来决定系统是否为生产部署准备好了,或者代码更改是否可以提交。谷歌开发人员的生产力取决于测试能否及时可靠地发现代码更改,或开发过程中的实际问题。

在提交前进行测试「即:pre-submit testing」,以便对本次提交进行代码审查,并验证代码变更质量是否可接受;在提交后再次进行测试「即:post-submit testing」,以决定项目是否达到发布质量。在提交代码和发布项目之前,该项目的所有测试都必须通过。

不幸的是,在我们的整个测试集合库中,我们持续会看到大约有 1.5% 的测试用例会识别为“不稳定”。“不稳定”测试用例的定义是:使用相同代码运行测试,结果有时是通过,有时是失败。。有很多原因 会导致测试返回不稳定的结果,例如并发操作,依赖于不确定或未定义的行为,不稳定的第三方代码,基础设施问题等等。

我们投入了大量精力来消除测试集中的不稳定因素,但总的来说,增长率与修复率大致相等,这意味着,我们处于一种平衡状态:提供了足够多有价值的测试有例,但偶尔会产生不稳定结果。我们几乎 16% 的测试用例都有一定程度的不稳定!这个数字很吓人;这意味着,在我们世界一流的工程师编写的测试中,超过七分之一的测试偶尔是由非代码或测试变更因素而导致的失败。

忽略报警是人类的天性

在进行提交后测试( post-submit testing )时,我们的持续集成(CI)系统会识别出那些原来是成功但本次执行失败的测试用例,以便我们可以调查导致失败的代码提交。我们在实践中发现,在我们观察到的从成功到失败的那些用例中,约有 84% 涉及到某个不稳定的测试!这会导致额外的重复工作,因为我们必须要确定新的失败是一个不可靠的结果,还是一个合法的失败。如果假阳性率高,那么,因不可靠的测试而忽视那些真正的失败,是很常见的事情。至少,我们的构建监视器通常会等到下一个 CI 周期再次运行此测试,以便来确定该次提交是否真的破坏了测试用例,从而延迟了识别实际问题的时间,并且可能导致待验证的变更代码量的堆积。

除了会有构建监控的成本之外,还要考虑,一般来说,每个项目都会包含1000个左右的独立测试用例。为了发布一个项目,我们要求最新的代码变必须通过所有这些测试才行。如果 1.5% 的测试结果是不可靠的,那么可能就会有 15 个测试用例失败,这需要构建警察「build cop」或开发人员投入进行失败原因的调查,这个成本比较高。而且在某些情况下,开发人员原本认为的失败结果不可靠,后来还会被发现的确是由于代码导致的合法失败。当系统发出虚假信号时,忽略报警是人类的天性。例如,这篇文章中提到的,关于飞行员无视 737 客机上的警报的事故报告。提交前测试也会出现同样的现象。同样 15 个左右的失败测试用例会阻碍代码提交,并给核心开发过程带来了代价高昂的延迟。在这个阶段如果忽略合法的测试失败,会导致提交有问题的代码。

如何处理不稳定的测试

在提交前测试期间,我们有几种针对不稳定测试用例的缓解策略,包括只重新运行失败测试的能力,以及在测试失败时自动重新运行测试用例的选项。我们甚至有一种方法来表示一个测试是不可靠的,邓:只有当它连续三次失败时,它才会报告失败。这减少了误报,并鼓励开发人员在自己的测试中忽略这些不稳定,除非他们的测试开始连续失败 3 次。然而,这并不是一个完美的解决方案。

想象一下,一个被标记为「不稳定」的测试用例让原本只需要等 15 分钟集成测试用例通过的代码提交,变成了直到完成 3 次试验或 45 分钟后,才会发现测试失败了,然后还要确定这个失败的测试用例是否鬹的需要修复,或者再试验是否连续三次失败。

其他缓解策略包括:

  • 开发一种工具,用来监控测试不稳定。如果不稳定性过高,它会自动将这个测试用例隔离出去。「隔离」是指:将测试从关键路径中移除,并为开发人员提交一个 bug ,以减少不稳定。这可以防止它成为开发人员的问题,但很容易掩盖测试代码中的真实竞争条件或其他缺陷。

  • 另一个工具检测测试不稳定程度的变化,并识别导致测试不稳定程度发生变化的那个代码变更。

总之,测试不稳定是一个重要的问题,谷歌正在持续投资于在我们的整个代码库中检测、缓解、跟踪和修复测试不稳定。例如:

  • 我们成立了一个专门团队,致力于提供有关测试不稳定的准确且及时的信息,以帮助开发人员和构建监控器,使他们知道自己是否受到测试不稳定的影响。

  • 当我们分析来自不稳定测试用例执行的数据时,我们看到了这些不稳定与某些特征具有相关性的线索,找到这些特征后,让我们能够在不重新运行测试的情况下准确地识别出哪些是不稳定的测试结果。

通过不断提升谷歌团队的技术水平,我们的目标是消除核心开发人员工作流程中因测试不稳定而产生的摩擦力。

参考阅读:

不稳定的测试是自动化测试的主要挑战之一(第一部分)

不稳定的测试是自动化测试的主要挑战之一(第二部分)

注:

本文中的数据为 2016 年的数据。根据 2020 年出版的《谷歌软件工程》一书,不稳定测试的比例要好很多。

原文作者:John Micco
发表时间:May 27, 2016
原文链接:Flaky Tests at Google and How We Mitigate Them