有条件地在赛普拉斯中跳过测试

时间:2019-02-05 08:27:53

标签: javascript mocha cypress

我正在尝试确定是否可以有条件地跳过测试套件中的测试it()并处理其异步特性。

我已经在赛普拉斯文档https://docs.cypress.io/guides/core-concepts/conditional-testing.html中阅读了有关条件测试的信息,并在https://mochajs.org/上了解了mochajs文档。

我的目的是检查网站上是否显示错误,如果没有,请跳过测试。否则,继续进行断言。

我要在赛普拉斯进行测试的来自mochajs的代码段为:

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

所以我在赛普拉斯拥有的是:

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的异步功能?

5 个答案:

答案 0 :(得分:3)

Cypress现在还提供了一个库@cypress/skip-test,该库可以通过以下方式提供更多控件:

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

DISCLOSE:我与Cypress没有关联。

答案 1 :(得分:2)

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

  

我正在尝试确定是否能够有条件地跳过测试套件中的测试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 :(得分:2)

我认为您已经快到了,但是您需要异步回调模式来代替同步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预期或微调器正在等待什么,但是您可以看到这种模式更加整洁并以受控方式测试所有路径。

答案 3 :(得分:0)

我使用的是@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,所以当我在本地运行时,不会跳过测试。

答案 4 :(得分:-1)

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

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

例如:

                plotArea: {
                dataLabel: {
                    visible: false
                },
                dataPointStyle: {
                            "rules":
                            [
                                {
                                    "dataContext": {"idTurnover": {"min": 0}},
                                    "properties": {
                                        "color":"sapUiChartPaletteSemanticBad"
                                    },
                                    "displayName":"Loss"
                                },
                                {
                                    "dataContext": {"idTurnover": {"max": 0}},
                                    "properties": {
                                        "color":"sapUiChartPaletteSemanticGood"
                                    },
                                    "displayName":"Profit"
                                }                                       
                            ],
                            "others":
                            {
                                "properties": {
                                     "color": "sapUiChartPaletteSequentialHue1"
                                },
                                    "displayName":"Cost"                                    
                            }
                        }                    
            },