如何使用 Cypress Cucumber 预处理器实现对单个测试的重试?

How to achieve retries for individual tests using Cypress Cucumber Preprocessor?

我目前面临的挑战是实现单独的测试重试,以稳定一小组特定的测试,这些测试依赖于某些后台处理,因此往往不稳定。我将 Cypress 9.2.0 与 TypeScript 和 Cypress Cucumber Preprocessor 4.3.1 一起使用。

为了提供更多细节,应用程序接收在后台处理的事件(通常最多需要 1-2 秒),然后创建数据记录。然后这些记录显示在UI中的table.

在某些 Cucumber 场景中,我对这些情况进行了端到端的测试。由于处理有时需要更长的时间,我想预防性地包括仅适用于这些测试用例的重试,更具体地说是检查 table.[=12 中最终显示的场景的“Then”步骤=]

由于不幸的是,像标准 Cypress 测试中的单独测试重试不适用于 Cucumber 预处理器,并且 cypress.json 中的全局测试重试也有问题,我想知道是否有另一种方法可以实现这一点?

正常赛普拉斯测试重试的文档:https://docs.cypress.io/guides/guides/test-retries

我找到了解决我的问题的方法,尽管一般来说这个解决方案可能并不完全理想。但首先,我还想提一下我之前尝试过但对我不起作用的方法:

  1. Individual Test Retries 遗憾的是,在使用 Cypress Cucumber 预处理器时无法使用特定测试步骤。

  2. Global Test Retries 不幸的是,问题中已经提到了与 Cucumber 预处理器有关的错误。

  3. 我尝试过的另一种方法是使用 cy.should() with a callback 但也没有成功。

  4. 第四种方法基于conditional testing and finally the one that brought me to the following solution, also considering the thoughts from this post如何在元素不可用时不中断赛普拉斯测试:

Then('the results related to some search keyword {string} are shown in the table', (search: string) => {
  checkTableWithRetries(search, 2);
});

function checkTableWithRetries(searchCriteria: string, retries: number) {
  cy.get('table').then(($table) => {
    if (checkIfTableRowExists($table) || retries === 0) {
      cy.get('table').find('tbody').contains('td', searchCriteria);
    } else {
      const time = retries === 1 ? 10000 : 5000;
      cy.wait(time);

      search(searchCriteria);
      checkTableWithRetries(searchCriteria, retries - 1);
    }
  });
}

function checkIfTableRowExists(element: JQuery<HTMLTableElement>) {
  return element.find('tbody').find('tr').length === 1;
}

function search(search: string) {
  cy.getByTestId('search-input').clear().type(`${search}`).should('have.value', `${search}`);
  cy.intercept('GET', `/api/endpoint**`).as('search');
  cy.getByTestId('search-button').click();
  cy.wait('@search');
}

如果一个元素被创建并显示在 table 中,代码确保我可以连续多次检查不同的延迟。如果重复x次后元素仍然不存在,则可以认为确实有错误。

澄清一下,使用的函数 cy.getByTestId() 不是标准的 Cypress 命令,而是根据官方最佳实践部分 here.

中的建议作为自定义命令添加的
Cypress.Commands.add('getByTestId', (selector, ...options) => {
  return cy.get(`[data-test=${selector}]`, ...options);
});