【问题标题】:Skipping a test in Cypress conditionally有条件地跳过赛普拉斯中的测试
【发布时间】:2020-08-31 22:54:00
【问题描述】:

我正在尝试找出是否能够有条件地跳过我的测试套件中的测试 it() 并处理其异步性质。

我在 Cypress 文档 https://docs.cypress.io/guides/core-concepts/conditional-testing.html 和 mochajs 文档中阅读了有关条件测试的内容 https://mochajs.org/

我的目的是检查网站上是否显示错误,如果出现则跳过测试。否则继续断言。

我试图在赛普拉斯进行测试的 mochajs 代码 sn-p 是:

it('should only test in the correct environment', function() {
  if (/* check test environment */) {
    // make assertions
  } else {
    this.skip();
  }
});

所以我在 Cypress 中得到的是:

it('shows the list', function() {
    if (queryFailed()) {
      this.skip();
    } else {
      cy.get('.list')
        .should('be.visible')
    }

请注意,我将it() 中的箭头函数更改为function(),以便我可以使用this

queryFailed() 是一个检查查询是否成功的函数。

function queryFailed() {
  cy.get('.spin')
    .then($container => {
      const htmlLoaded = $container[0].innerHTML;

      if (htmlLoaded.indexOf('List') !== -1) {
        return false;
      }

      if (htmlLoaded.indexOf('error') !== -1) {
        return true;
      }

      cy.wait(1000);
      queryFailed();
    });
}

简单地说,如果我等待的div 元素的内容有“错误”,那么我知道查询失败所以我返回true,否则我返回false。

我在调试后的测试中看到的是,即使条件运行良好,JS 的异步性质也会同时执行 else 语句中的代码而不是 if。所以最终的输出就好像完全没有条件一样,因为一切都经过了测试。

有没有更好的方法来处理 JS 的这种异步特性?

【问题讨论】:

    标签: javascript mocha.js cypress


    【解决方案1】:

    感谢您的详细描述! 我为您的第一个问题提供了解决方案

    我正在尝试找出是否能够有条件地跳过我的测试套件中的测试 it() 并处理其异步性质。

    使用环境变量,我向您报告我的解决方案(实际在我的管道中使用)。

    if (!Cypress.env("SKIP_E2E_TESTS")) {
      it(...);
    }
    

    在我的 package.json 文件中,我有一个看起来像这样的脚本

    "test": "CYPRESS_SKIP_E2E_TESTS=true npm-run-all --parallel --silent test:unit test:cypress",
    

    我的目标和你一样,我想在某些情况下禁用一些测试(在我的例子中是 CI 管道)。

    所以把整个测试放到一个条件中,而不是一个条件测试。

    如果您需要更多帮助,请告诉我 ?

    【讨论】:

    • 感谢您的回答!我知道在你的情况下,如果你想提前跳过考试,你想通过,对吧?就我而言,我打算根据运行时发生的情况来执行此操作(我知道这很危险,但这是一个棘手的情况:)
    【解决方案2】:

    赛普拉斯现在还提供了一个库@cypress/skip-test,它可以通过

    • cy.skipOn
    • cy.onlyOn
    • isOn
    • 布尔标志
    • 有头/无头环境
    • 环境

    披露:我与赛普拉斯无关。

    【讨论】:

    • 我们可以在skipOn中传递自定义消息吗?在我的情况下,它没有进入cy关键字,我必须在每个类中导入skip-test:/
    【解决方案3】:

    我想你差不多了,但是你需要异步回调模式而不是同步 if () {...} else {...} 模式。

    it('shows the list', function() {
    
      const whenFailed = function() {
        this.skip()
      }
    
      const whenSucceeded = function() {
        cy.get('.list').should('be.visible')
      }
    
      queryFailed(whenFailed, whenSucceeded);
    }
    
    function queryFailed(whenFailed, whenSucceeded) {
      cy.get('.spin')
        .then($container => {
          const htmlLoaded = $container[0].innerHTML;
    
          if (htmlLoaded.indexOf('List') !== -1) {
            whenSucceeded();
            return;
          }
    
          if (htmlLoaded.indexOf('error') !== -1) {
            whenFailed();
            return;
          }
    
          cy.wait(1000);
          queryFailed(whenFailed, whenSucceeded);
        });
    }
    

    但是,我注意到对 queryFailed() 的递归调用,看起来您正在手动重试旋转容器的内容。

    Cypress 内置了重试功能,因此您只需确定结果可能需要的最长时间(例如 20 秒),它会在所需内容到达时立即结束命令,或者测试失败如果它没有在 20 秒内发生,则完全不发生。

    此外,您应该控制微调器正在等待的任何事情的成功/失败(例如,通过 XHR 获取列表)。所以你应该把测试分成两份——一份代表成功,一份代表失败。

    context('when the list loading succeeds' function() {
    
      it('shows the list', function() {
        // Mock XHR success here
        cy.contains('.spin', 'List', { timeout: 20000 });
        cy.get('.list').should('be.visible');
      })
    
      it('does not show an error message', function() {
        ...
      })
    
    })
    
    context('when the list loading fails' function() {
    
      it('does not show the list', function() {
        // Mock XHR failure here
        cy.contains('.spin', 'error', { timeout: 20000 });
        cy.get('.list').should('not.be.visible');
      })
    
      it('shows an error message', function() {
        ...
      })
    
    })
    

    这有点粗糙,因为我不知道预期的确切 HTML,或者微调器正在等待什么,但您可以看到这种模式更加整洁,并以受控方式测试所有路径。

    【讨论】:

    • 非常感谢您的详尽回答,它对我有用!我只需要将whenFailed 函数定义更改为箭头函数,这样this 就会拥有it 的上下文。
    • 我们如何在 Cypress Cucumber 中实现同样的效果?
    【解决方案4】:

    我正在使用@NoriSte 的答案的改编版本,它仍然注册测试,但被跳过:

    const maybeDescribe = Cypress.env('SOME_ENV_VAR') ? describe : describe.skip
    
    maybeDescribe('Test suite', function() { /* ... */ })
    

    然后类似地,在 CI 上,我想跳过测试:

    export CYPRESS_SOME_ENV_VAR=
    $(npm bin)/cypress run
    

    我的源代码控制cypress.json 定义了SOME_ENV_VAR,因此当我在本地运行时,不会跳过测试。

    【讨论】:

      【解决方案5】:

      Cypress Real World Appa payment application to demonstrate real-world usage of Cypress testing methods, patterns, and workflows 包含一些工作流,用于在 CI 中有条件地运行测试,以及针对移动视口更改的工作流。

      此外,从赛普拉斯 v4.8.0 开始,某些 Test Configurations 可能会应用于套件或个人测试。

      例如:

      it('Show warning outside Chrome', {  browser: '!chrome' }, () => {
        cy.get('.browser-warning')
         .should('contain', 'For optimal viewing, use Chrome browser')
      })
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-14
        • 1970-01-01
        • 2023-01-12
        • 2019-10-24
        • 2021-10-20
        • 2020-05-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多