我们在 Gradle 中如何处理不稳定的测试
介绍
测试不稳定性是自动化测试的主要挑战之一。尽管 Gradle 的重点是提高开发者生产力,但 Gradle 自身的开发也受到不稳定的自动化测试的困扰。这篇博客解释了在开发 Gradle 时的一些最佳实践,这些实践在我们多年与不稳定测试的斗争中被证明是有效的。
故事 #
像许多其他项目一样,Gradle 的每次提交都必须通过数万个自动化测试。任何微小的不稳定性都可能导致开发者生产力下降。当我在 5 年前加入 Gradle 时,CI 充满了不稳定的测试失败 - 人们会一遍又一遍地重新运行构建,希望足够幸运以获得绿色构建。
后来,我们成立了一个专门的开发者生产力团队来处理 CI 上的所有不稳定性,尤其是测试不稳定性。以下是我们逐步进行的方法。
重试失败的测试 #
当测试失败时,我们如何确定它是否不稳定?最简单的方法显然是立即重试失败的测试:如果第二次运行成功,则失败的测试是不稳定的。根据经验,只需再次重新运行失败的测试一次,就可以将由于不稳定性导致的测试失败减少 90%。
许多 CI 系统可以识别出这种不稳定的测试,并自动将构建标记为绿色
在此示例中,第一次运行由于网络错误而失败,但重新运行成功。TeamCity 识别出这种情况并“静音”了测试失败。
如果构建连接到 Gradle Enterprise 实例,并且该构建已发布 构建扫描,您可以在测试仪表板中看到不稳定的测试
在 Gradle 中,我们使用 Test Retry Gradle 插件 自动重试失败的测试类。请查阅文档,了解如何在您的构建中采用它。
重试失败测试的其他技术 #
如果您没有使用 Gradle,那也没关系。有许多替代方案提供类似的功能
以上所有工具都受到 Gradle Enterprise 不稳定测试检测 的支持,它提供了很棒的 测试失败分析 功能,以帮助您诊断测试不稳定性。
借助不稳定的测试仪表板,您可以浏览不稳定测试用例或类的趋势和历史记录。这在排除不稳定测试故障时非常有帮助。
隔离过于不稳定的测试 #
重试失败的测试足够吗?答案是,不幸的是,否。Gradle 代码库中的某些测试非常不稳定,以至于有时即使重新运行两次或更多次也会失败。这些不稳定的测试通常是由有缺陷的生产代码或测试基础设施引起的,并且严重损害了开发者生产力。
在 Gradle 中,当我们发现这种“过于不稳定”的测试时,我们会隔离它们。隔离意味着这些测试与 CI 管道隔离,以获取开发者反馈。换句话说,它们从开发者的视线中消失,并且不会再阻止开发者。
它们去哪里了?我们会丢失这些“过于不稳定”的测试的测试覆盖率吗?不,它们会在夜间 CI 作业(我们称之为 Flaky Test Quarantine
)中收集和执行,该作业每天运行一次,如下所示
通过手动将自定义 @Flaky
注解 添加到测试类或方法上来隔离“过于不稳定”的测试,一旦我们看到任何发生。我们还引入了 三种策略 来选择要运行的测试
EXCLUDE
: 选择运行所有测试,排除@Flaky
测试。这是正常 CI 管道的默认策略。ONLY
: 仅选择@Flaky
测试运行。这是Flaky Test Qurantine
作业的策略。INCLUDE
: 选择运行所有测试,包括@Flaky
测试。
(有关如何使用不同的测试框架实现这些策略,请参阅 @Flaky
注解 中的 Javadoc。)
修复不稳定的测试 #
以上所有方法都不能解决不稳定测试中的真正问题 - 它只是隐藏了问题,并给您一种虚假的安全感。必须采取行动来修复有缺陷的代码,即不稳定测试的根本原因。
感谢 Gradle Enterprise 不稳定测试检测 功能中的测试仪表板,我们可以轻松地
- 统计所有不稳定测试的数量。
- 按发生频率对所有不稳定测试进行排序。
- 浏览特定不稳定测试的历史记录。这很重要,因为我们可以轻松识别引入不稳定测试的人员。
我们每周审查所有不稳定测试一次,并采取行动使其总数尽可能低。以下是我们进行审查的方式
通过这种方式,大多数新的不稳定测试都会立即被注意到并分配。无法分配的不稳定测试将在“不稳定修复日”收集和修复。“不稳定修复日”是一个 1 或 2 天的黑客马拉松,当不稳定测试数量超过某个阈值时(例如,占测试总数的 1%)我们会组织该活动。在不稳定修复日期间,所有开发团队共同努力,专注于修复累积的不稳定测试。
总结 #
不稳定测试令人痛苦,但可以采取措施防止它们损害开发者生产力。这篇博客描述了我们在 Gradle 开发中采取的措施,以控制不稳定测试:重试所有失败的测试,隔离过于不稳定的测试,并通过团队合作修复不稳定测试。
反馈 #
如果您对我们的 论坛 或 Gradle 社区 Slack 有任何疑问,请告诉我们。