Cypress 中的异步特性
Cypress 基于 node.js 服务器构建,并使用 Javascript 编程语言。任何依赖于 node.js 的内容本质上都是异步的,因此 Cypress 命令也以这种模式工作。
当我们在测试用例中有一组测试步骤时,所有步骤都会并行开始执行,而不会等待前一个步骤完成。在同步执行中,每个测试步骤按顺序运行,只有在前一个步骤执行完成后,我们才会进入下一步。
因此,在像 Cypress 这样的异步执行中,即使测试步骤是按顺序设计的,每个测试步骤也都是相互独立的。简而言之,在异步模式下,每个步骤都不会考虑前一个步骤执行的结果或状态,而只是简单地运行每个步骤。
Cypress 提供了一个包装器,确保其命令的测试执行按照开发顺序发生。因此,这些命令会同时执行,但它们会被排队。但是,如果 Javascript 命令与 Cypress 命令一起工作,它仍然是异步的。
示例
现在让我们执行一段 Cypress 代码:
// test suite describe('Tutorialspoint Test', function () { // test case it('Test Case1', function (){ // test step to launch a URL cy.visit("https://tutorialspoint.com/index.htm"); // enter test in the edit box cy.get('#gs_50d > tbody > tr > td'). should('have.length',2); // locate element with get and find method cy.get('#gs_50d > tbody > tr > td'). find('input') //enter test in the edit box .type('Cypress'); console.log('Tutorialspoint'); }); });
在触发上述代码执行时,如果我们打开浏览器控制台,我们会在浏览器加载之前就发现 Tutorialspoint 打印在上面。这证实了 console.log 测试步骤没有等待其他测试步骤,并立即在控制台中打印。
因此,我们看到,由于 console.log 是一个 Javascript 命令,它不会像 Cypress 复合命令那样进行排队,而是继续执行。Cypress 通过 promise 处理来顺序执行其步骤。
Promise 是一种编程语言,用于确定 Cypress 命令的状态。Promise 有三种状态,如下所示:
已解决(Resolved) - 如果测试步骤执行没有失败,则处于此状态。
挂起(Pending) - 如果正在等待测试步骤执行结果,则处于此状态。
已拒绝(Rejected) - 如果测试步骤执行失败,则处于此状态。
只有在前一个命令或 promise 响应已解决后,Cypress 中的以下命令才会执行。我们可以使用 then() 方法在 Cypress 代码中实现 promise。
示例
以下代码描述了在 Javascript 中为每个 Cypress 复合命令实现的 promise。这种实现使代码变得混乱且冗长。
// test suite describe('Tutorialspoint Test', function () { // test case it('Test Case1', function (){ return cy.visit('https://tutorialspoint.com/index.htm') .then(() => { return cy.get('.product'); }) .then(($element) => { return cy.click($element); }) }) })
Cypress 在内部处理 promise,并借助包装器来解决它们,我们可以实现我们的代码而无需考虑 promise 的状态。因此,代码的可读性大大提高。
上述 Cypress 代码,不使用 promise。
// test suite describe('Tutorialspoint Test', function () { // test case it('Test Case1', function (){ cy.visit('https://tutorialspoint.com/index.htm') cy.get('.product').click(); }) })
因此,Cypress 会考虑到测试用例中的下一步只有在前一个命令或 promise 处于已解决状态时才会执行。