如何检测和预防偶发性测试?

Blog
Author:
Incredibuild TeamIncredibuild Team
Published On:
6月 21, 2025
Estimated reading time:
1 minute

目录

酥脆适合形容糕点,但绝不应该是测试的特性

如果您曾经有过一次测试,前一刻通过,下一刻不及格,即使没有任何变化,您也可能会遇到不稳定的测试。这些不可预测的测试可能会使 CI/CD pipelines 脱轨并减慢发布速度。

但偶发性测试不一定是一个永久性的问题。事实上,你可以永久摆脱这些片状的东西。以下是对这个概念和对抗它的武器的仔细研究。

什么是偶发性测试?

偶发性测试是有时失败有时通过的自动化测试,即使相关代码保持完全相同。这些不一致的结果使得很难知道某些东西是否真的坏了。

这种测试失败在自动化 pipelines 中尤其危险,因为误报可能会阻止部署或导致团队忽略合法问题。

为什么测试是偶发性的?

偶发性测试不仅仅是随机发生的。大多数时候,这种行为背后有某种模式或某种原因。

以下是它们发生的一些最常见原因:

  • 时机问题:如果 timing 不正确,依赖于特定延迟或等待加载的测试可能会失败。
  • 并发问题 :当多个测试同时运行时,它们可能会相互干扰。如果它们共享文件或内存,则尤其常见。
  • 环境差异 :由于作系统或硬件的差异,测试在本地的行为方式可能与 CI 环境中的另一种方式相同。
  • 不可靠的第三方依赖项 :如果您的测试调用外部 API 或服务,则该服务中的任何不稳定都可能导致其失败。
  • 编写不佳的测试 :依赖于特定实现细节或脆弱的选择器的测试更有可能变得不稳定。
  • Order Dependency:某些测试仅在您之前运行某些测试时才会通过。当顺序发生变化时,它们会失败。

了解原因是解决问题的第一步。一旦确定了模式,您就可以开始解决每个偶发性测试背后的具体问题。

偶发性测试检测的重要性

为什么您应该关注偶发性测试?因为他们停留的时间越长,造成的伤害就越大。

不稳定的偶发性测试可能会削弱人们对测试套件的信任。开发人员可能会开始忽略失败,假设测试再次运行。这为真正的问题打开了大门。

它们还会减慢您的开发过程。重新运行测试和调试误报所花费的时间是构建产品所占用的时间。

总体而言,偶发性测试可以:

  • 延迟发布
  • 增加工程成本
  • 降低团队信心
  • 隐藏实际错误

简而言之,及早识别偶发性测试是 CI/CD 工作流程优化不可或缺的一部分。

如何检测偶发性测试?

检测偶发性测试并不总是那么容易,但有一些经过验证的方法可以提供帮助。

重复测试执行

发现偶发性测试的最简单方法之一是多次运行它。如果测试有时通过,有时失败,但没有任何代码更改,则您发现了一个碎片

分析历史测试数据

使用 CI/CD 工具检查过去的测试运行。查找模式:某些测试在特定分支上还是在一天中的特定时间更频繁地失败?JenkinsGitHub Actions 或 CircleCI 等工具可以帮助您跟踪和比较结果。

识别并行执行失败

某些测试仅在并行运行时失败。尝试按顺序运行相同的测试套件,然后并行运行,看看是否有差异。

监控执行时间

显示执行时间变化较大的测试可能是片状的。持续时间的突然峰值通常暗示潜在的计时或依赖项问题。

使用检测工具

有几种工具可以帮助检测偶发性测试:

  • 测试重试插件(例如,Jest Retry Times、pytest-rerunfailures)
  • 具有片状跟踪功能的 CI 仪表板
  • 标记不一致测试结果的自定义脚本

标记出潜在的偶发性测试后,请隔离它们以进行进一步检查并开始努力修复。

你如何修复偶发性测试?

修复不稳定的测试通常意味着深入研究测试本身并探索围绕它的系统。

首先重现薄片。这可能需要多次运行测试或修改环境以模拟测试失败的条件。

然后,根据原因,考虑以下解决方案:

  • 添加适当的等待或同步 :不要使用硬编码的延迟,而是等待特定条件,例如元素可见性或事件完成。
  • 模拟或存根外部依赖项 :这将删除 API 响应时间或 Internet 连接等变量。
  • 隔离共享资源 :如果您的测试正在使用共享文件、数据库或变量,请将其隔离,以便每个测试都获得自己的副本。
  • 重构复杂的测试逻辑 :简化并阐明测试正在执行的作。通常,不稳定的行为隐藏在过于复杂的测试代码中。
  • 使测试具有幂等性 :确保多次运行测试不会更改结果或环境。

修复偶发性测试类似于解决由不一致环境导致的构建失败。您需要消除隐藏变量并确保测试运行之间的稳定性。

这可能需要一些试验和错误,但现在投入时间修复不稳定的测试具有很高的回报。

如何防止偶发性测试

偶发性测试的最佳策略?一开始就不要让它们发生。

以下是您的团队可以采取的一些主动措施:

  • 遵循测试自动化最佳实践 :编写每个测试检查一个事物的重点测试。如果不需要,请避免依赖 UI。
  • 对不稳定的服务使用 Mocks:除非您专门测试集成,否则不要进行真正的 API 调用。
  • 保持测试独立 :任何测试都不应依赖于其他测试的结果。
  • 在干净的环境中运行测试 :使用容器或隔离的环境来降低系统噪音。
  • 定期分析测试失败 :在 CI 系统中构建警报或仪表板,以便及早发现问题。

更少的偶发性测试意味着更少的延迟和更快的反馈循环。减少开发团队的困惑意味着更好的结果。

偶发性测试:非常适合羊角面包,但不适合 pipelines

偶发性测试不仅令人讨厌。它们很昂贵。它们会减慢发布速度并破坏对测试套件的信任。但好消息是它们可以被检测和消除。

不要让片状的测试削弱您的信心。立即采取行动,提高测试稳定性并优化 CI/CD 工作流程,同时提高开发人员的工作效率

关于偶发性测试的常见问题解答

强耦合的测试和偶发性测试有什么区别?

当底层代码发生变化时,强耦合性测试会中断,即使更改不应影响结果。它们对实现细节很敏感,例如网页的确切结构或变量的命名。

另一方面,Flaky 测试即使代码没有更改,也会随机失败。他们可能在前一分钟过去了,下一分钟就失败了(没有任何明确的原因)。

虽然强耦合性测试本质上是脆弱的,但偶发性测试是不一致的。每个问题都值得您关注,但需要不同的解决方案。

什么是偶发性测试的例子?

这是 Python 中的一个经典示例:

python

CopyEdit

 

def test_login():

 

    driver.get(https://example.com/login)

 

    driver.find_element_by_id(username).send_keys(user)

 

    driver.find_element_by_id(password).send_keys(pass)

 

    driver.find_element_by_id(login-button).click()

 

    assert Welcome in driver.page_source

如果页面加载缓慢,则此测试可能会失败。添加适当的等待可以使此测试更加稳定。

如何测量偶发性测试?

衡量不稳定的测试有助于跟踪改进并确定要修复的内容的优先级。

  • Flake Rate (片状速率): 计算测试失败的频率除以测试运行的次数。20% 的剥落率意味着每 5 次运行中就有 1 次失败。
  • 稳定性分数 : 一些团队使用基于测试持续时间、历史通过率和重播次数的自定义评分系统。
  • CI 分析工具 :许多平台,如 Jenkins 或 GitLab,可以为您提供偶发性测试报告。

另一方面,跟踪这些指标可以帮助您抓住 issn,低命中率可能表明可能存在效率低下的情况,例如冗余任务执行。提高缓存命中率可能具有挑战性,但优化这些可以显著加快构建速度并减少资源消耗。