Gradle 中如何处理不稳定的测试

测试不稳定是自动化测试的主要挑战之一。尽管 Gradle 的重点是提高开发人员的生产力,但 Gradle 本身的开发也受到不稳定自动化测试的影响。这篇博文解释了在开发 Gradle 时的一些最佳实践,这些实践在我们多年与不稳定测试作斗争中被证明是有效的。

故事

与许多其他项目一样,Gradle 的每次提交都必须通过数万次自动化测试。任何微小的不稳定性都可能导致开发人员生产力下降。五年前我加入 Gradle 时,CI 充满了不稳定的测试失败 - 人们会一遍又一遍地重新运行构建,希望幸运地获得绿色构建。

后来,我们开始了一个专门的开发人员生产力团队来处理 CI 上的所有不稳定性,尤其是测试不稳定性。以下是我们一步一步的操作方法。

重试失败的测试

当测试失败时,我们如何确定它是否不稳定?最简单的方法显然是立即重试失败的测试:如果第二次运行成功,则失败的测试是不稳定的。根据经验,只需重新运行失败的测试一次,就可以将由于不稳定性导致的测试失败减少 90%。

许多 CI 系统可以识别出这种不稳定的测试,并自动将构建标记为绿色。

teamcity-muted-failure

在这个例子中,第一次运行由于网络错误而失败,但重新运行成功。TeamCity 识别了这种情况并“静音”了测试失败。

如果构建连接到 Gradle Enterprise 实例,并且该构建发布了 Build Scan,您可以在测试仪表板中看到不稳定的测试。

build-scan-flaky-test

在 Gradle 中,我们使用 Test Retry Gradle 插件 自动重试失败的测试类。请参阅文档了解如何在您的构建中采用它。

其他重试失败测试的技术

如果您没有使用 Gradle,也没关系。有很多替代方案提供类似的功能。

所有上述工具都受 Gradle Enterprise 不稳定测试检测 支持,该检测提供了很棒的 测试失败分析 功能来帮助您诊断测试不稳定性。

flaky-test-trend

使用不稳定测试仪表板,您可以浏览不稳定测试用例或类的趋势和历史记录。这在排查不稳定测试时非常有帮助。

隔离过于不稳定的测试

重试失败的测试就足够了吗?答案是,不幸的是,不。Gradle 代码库中的一些测试非常不稳定,以至于有时即使重新运行两次或更多次也会失败。这些不稳定的测试通常是由有缺陷的生产代码或测试基础设施引起的,并且严重损害了开发人员的生产力。

在 Gradle 中,当我们发现这种“过于不稳定”的测试时,我们会将其隔离。隔离意味着这些测试与 CI 管道隔离,以供开发人员反馈。换句话说,它们从开发人员的视线中消失,不再阻碍开发人员。

这些测试去哪里了?我们是否会失去这些“太不稳定”测试的测试覆盖率?不会,它们会被收集起来,并在每天运行一次的夜间 CI 任务中执行(我们称之为 Flaky Test Quarantine),就像这样

steps

一旦我们发现任何“太不稳定”的测试,就会通过手动添加自定义的 @Flaky 注解 到测试类或方法上,将它们隔离。我们还引入了 三种策略 来选择要运行的测试

  • EXCLUDE:选择运行所有测试,除了 @Flaky 测试。这是正常 CI 管道的默认策略。
  • ONLY:只选择运行 @Flaky 测试。这是 Flaky Test Qurantine 任务的策略。
  • INCLUDE:选择运行所有测试,包括 @Flaky 测试。

(有关如何在不同的测试框架中实现这些策略,请参阅 @Flaky 注解 中的 Javadoc。)

修复不稳定的测试

以上所有内容都没有解决不稳定测试中的真正问题 - 它只是隐藏了问题,并给你一种虚假的安全感。必须采取行动来修复有缺陷的代码,即不稳定测试的根本原因。

感谢 Gradle Enterprise Flaky Test Detection 功能中的测试仪表板,我们可以轻松地

  • 统计所有不稳定测试的数量。
  • 按不稳定测试发生的频率对其进行排序。
  • 浏览特定不稳定测试的历史记录。这很重要,因为我们可以轻松地识别出引入不稳定测试的人。

我们每周审查一次所有不稳定测试,并采取措施将其总数保持在尽可能低的水平。以下是我们进行审查的方式

通过这种方式,大多数新的不稳定测试都会被立即注意到并分配。无法分配的不稳定测试将被收集起来,并在“不稳定修复日”进行修复。“不稳定修复日”是我们组织的为期 1 或 2 天的编程马拉松,当不稳定测试数量超过某个阈值(例如,总测试数量的 1%)时就会举行。在不稳定修复日,所有开发团队都会共同努力,专注于修复积累的不稳定测试。

总结

不稳定的测试很痛苦,但可以采取措施防止它们损害开发人员的生产力。这篇博文描述了我们在 Gradle 开发中采取的措施来控制不稳定测试:重试所有失败的测试,隔离过于不稳定的测试,并通过团队合作修复不稳定的测试。

反馈

如果您有任何问题,请在我们的 论坛Gradle 社区 Slack 上与我们联系。

讨论