摆脱前端测试恶梦:摇摆不定的测试(二)

发表于:2021-7-08 09:45

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:前端小工    来源:掘金

  对抗软弱性的方法
  我们已经确定了导致松散性的三个原因。我们可以在此基础上建立我们的反击策略!当然,当你遇到不稳定的测试时,牢记这三个原因,你已经收获颇丰。你已经知道应该寻找什么以及如何改进测试。然而,除此之外,还有一些策略可以帮助我们设计、编写和调试测试,我们将在下面的章节中一起看一下。

  关注你的团队
  你的团队可以说是最重要的因素。作为第一步,承认你有一个测试不稳定的问题。获得整个团队的承诺是至关重要的然后,作为一个团队,你需要决定如何处理不稳定的测试。
  在我从事技术工作的这些年里,我遇到了四个团队用来对付不稳定的策略。
  什么都不做,接受不稳定的测试结果。
  当然,这个策略根本就不是一个解决方案。测试不会产生任何价值,因为你不能再相信它了--即使你接受它的缺陷。所以我们可以很快跳过这个问题。
  这个策略在我职业生涯的开始阶段很常见,导致了我前面提到的反应。有一些人接受重试测试直到它们通过。这种策略不需要调试,但它很懒惰。除了隐藏问题的症状外,它还会使你的测试套件更加缓慢,这使得该解决方案不可行。然而,这个规则可能有一些例外,我将在后面解释。

  删除并忘记测试
  这个是不言自明的。简单地删除不稳定的测试,这样它就不会再干扰你的测试套件。当然,这将节省你的钱,因为你不需要再调试和修复测试。但它的代价是失去了一点测试覆盖率和失去潜在的错误修复。测试的存在是有原因的!不要通过删除测试来射杀信使。

  隔离和修复
  我在这个策略上取得了最大的成功。在这种情况下,我们会暂时跳过测试,并让测试套件不断提醒我们有一个测试被跳过。为了确保修复工作不被忽视,我们会在下一个冲刺阶段安排一个任务。机器人提醒也很有效。一旦导致浮动的问题被修复,我们将再次整合(即取消跳过)测试。不幸的是,我们会暂时失去覆盖率,但它会随着修复而回来,所以这不会花很长时间。

  这些策略帮助我们处理工作流层面的测试问题,而且我不是唯一遇到过这些问题的人。在他的文章中,Sam Saffron也得出了类似的结论。但在我们的日常工作中,它们对我们的帮助是有限的。那么,当这样的任务来到我们身边时,我们该如何进行呢?

  保持测试隔离
  在计划你的测试用例和结构时,始终保持你的测试与其他测试隔离,这样它们就能以独立或随机的顺序运行。最重要的步骤是在测试之间恢复一个干净的安装。此外,只测试你想测试的工作流程,并且只为测试本身创建模拟数据。这个捷径的另一个好处是,它可以提高测试性能。如果你遵循这些要点,就不会有其他测试的副作用或遗留的数据妨碍你。
  下面的例子来自于一个电子商务平台的UI测试,它涉及到客户在店面的登录。该测试是用JavaScript编写的,使用的是Cypress框架)。
// File: customer-login.spec.js
let customer = {};

beforeEach(() => {
    // Set application to clean state
    cy.setInitialState()
      .then(() => {
        // Create test data for the test specifically
        return cy.setFixture('customer');
      })
}):

  第一步是将应用程序重置为一个干净的安装。这是作为beforeEach 生命周期钩子的第一步,以确保每次都能执行重置。之后,专门为测试创建测试数据--对于这个测试案例,将通过一个自定义命令创建一个客户。随后,我们可以从我们想要测试的一个工作流开始:客户的登录。

  进一步优化测试结构
  我们可以做一些其他的小调整,使我们的测试结构更加稳定。第一个是很简单的。从小型测试开始。如前所述,你在测试中做的越多,可能出错的就越多。尽量保持测试的简单,避免在每个测试中出现大量的逻辑。
  当涉及到不假设数据的顺序时(例如,在UI测试中处理列表中的条目顺序时),我们可以设计一个测试来独立于任何顺序的功能。回到网格中信息的例子,我们不会使用伪选择器或其他对顺序有强烈依赖性的CSS。我们可以使用文本或其他对顺序无所谓的东西来代替nth-child(3) 选择器。例如,我们可以使用这样的断言:"在这个表中给我找一个有这一个文本字符串的元素"。
  等等!测试重试有时是可以的?
  重试测试是一个有争议的话题,而且是理所当然的。我仍然认为,如果测试被盲目地重试直到成功,那是一种反模式。然而,有一个重要的例外。当你无法控制错误时,重试可以是最后的手段(例如,排除来自外部依赖的错误)。在这种情况下,我们不能影响错误的来源。然而,这样做时要格外小心。在重试测试时,不要对松散性视而不见,当一个测试被跳过时,要使用通知来提醒你。
  下面的例子是我在我们的CI中使用的GitLab的例子。其他环境可能有不同的语法来实现重试,但这应该能让你体会到。
test:
    script: rspec
    retry:
        max: 2
        when: runner_system_failure

  在这个例子中,我们要配置的是,如果工作失败,应该进行多少次重试。有趣的是,如果运行器系统中出现错误(例如,作业设置失败),可以重试。我们选择只在docker设置失败的情况下重试我们的作业。
  注意,这将在触发时重试整个作业。如果你希望只重试有问题的测试,那么你需要在你的测试框架中寻找一个功能来支持这个。下面是一个来自Cypress的例子,它从第5版开始就支持单个测试的重试。
{
    "retries": {
        // Configure retry attempts for 'cypress run`
        "runMode": 2,
        // Configure retry attempts for 'cypress open`
        "openMode": 2,
    }
}

  你可以在Cypress的配置文件中激活测试重试,cypress.json 。在那里,你可以在测试运行器和无头模式中定义重试的尝试。

  使用动态等待时间
  这一点对所有类型的测试都很重要,但尤其是UI测试。我怎么强调都不为过。永远不要使用固定的等待时间--至少在没有很好的理由的情况下不要。如果你这样做,请考虑可能的结果。在最好的情况下,你会选择过长的等待时间,使测试套件比它需要的更慢。在最坏的情况下,你将不会等待足够长的时间,所以测试不会进行,因为应用程序还没有准备好,导致测试以一种不稳定的方式失败。根据我的经验,这是导致测试不稳定的最常见原因。
  相反,使用动态等待时间。有许多方法可以做到这一点,但Cypress处理得特别好。
  所有的Cypress命令都拥有一个隐含的等待方法。它们已经检查了该命令所应用的元素是否在DOM中存在指定的时间--指向Cypress的重试能力。然而,它只检查是否存在,仅此而已。所以我建议更进一步--等待你的网站或应用程序的用户界面中的任何变化,而这些变化也是真实的用户会看到的,比如用户界面本身或动画中的变化。

  这个例子在元素上使用了一个明确的等待时间,选择器为.offcanvas 。只有当该元素在指定的超时之前是可见的,测试才会进行,你可以配置这个超时。
// Wait for changes in UI (until element is visible)
cy.get(#element).should('be.visible');

  在Cypress中,动态等待的另一个巧妙的可能性是其网络功能。是的,我们可以等待请求的发生,并等待其响应的结果。我特别经常使用这种等待。在下面的例子中,我们定义了要等待的请求,使用一个wait 命令来等待响应,并断言其状态代码。
// File: checkout-info.spec.js

// Define request to wait for
cy.intercept({
    url: '/widgets/customer/info',
    method: 'GET'
}).as('checkoutAvailable');

// Imagine other test steps here...

// Assert the response’s status code of the request
cy.wait('@checkoutAvailable').its('response.statusCode')
  .should('equal', 200);

  这样一来,我们就可以根据我们的应用需要精确地等待,使测试更加稳定,不容易因为资源泄漏或其他环境问题而出现故障。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号