Cypress:等待不可预测的组件从专有集合中渲染?

Jef*_*ner 7 cypress

为了进行彻底的测试,我的服务(UI+后端)通过多个部署环境进行迁移:ex DEV、STAGE、DEMO 和 PROD。当该服务迁移这些测试环境时,其 UI 会等待来自后端的异步更新,这作为测试压力源可能会异常缓慢;因此,加快速度不是一种选择,也不是嘲笑响应。

UI 测试涉及等待异步更新响应以确定将专门呈现哪些 React 组件。这些 React 组件将是具有不可预测内容/文本的部分/div,因此不是一个选项。Cypress contains

处理缓慢异步更新的典型解决方案是使用固定延迟Cypress wait:一堆毫秒、十分之几秒,甚至几秒。然而,固定延迟越长,您的测试就越脆弱

这是我的脆弱 Cypress 测试代码的示例:

cy.get('div.main')
  .then( ($divMain) => {
    cy.wait(5000) // wait 5 seconds

    const boolStateA = $divMain.find('section.A').length > 0;
    const boolStateB = $divMain.find('section.B').length > 0;

    if (boolStateA( {
      // Do ...
    } else if ( boolStateB ) {
      // Do something else ...
    }
  })
Run Code Online (Sandbox Code Playgroud)

然而,等待 5 秒后,并不能绝对确定其中一个组件是否实际渲染。如果两者均未呈现或均未呈现,则这是意外状态。

那么我怎样才能等待这些组件中的任何一个都不使用cy.wait()or进行渲染呢cy.contains

谢谢

Ala*_*paz 8

要等待<section class="A">or之一<section class="B">,请使用多个选择器

Cypress 将等待第一个出现,您可以添加一个超时(因为 5 秒略高于默认超时)。

cy.get('div.main')
  .find('section.A, section.B', {timeout:5_000})
  .then($section => {

    if ($section.hasClass("A") {          
      
    } 

    if ($section.hasClass("B") {          
      
    }
  })
Run Code Online (Sandbox Code Playgroud)

另一个例子:Cypress 断言 A 或 B


Gra*_*arf 5

cypress 的建议是让您的测试具有确定性。意思是,弄清楚如何确保您的产品在测试运行时始终处于已知状态。这通常是通过模拟、路由或向后端发送消息来提供(或可能获取)预定状态来完成。

内联超时可能比 cy.wait() 好一点,但这并不能解决您的未知状态问题。

cy.get('.mobile-nav', { timeout: 10000 })
  .should('be.visible')
  .and('contain', 'Home')
Run Code Online (Sandbox Code Playgroud)

或者,您可以更新应用程序以包含测试等待的隐藏完成状态。

例子:

<div data-cy="SectionLoaded">SectionA</div> 
Run Code Online (Sandbox Code Playgroud)

通过这种方式,测试只需要等待一件事,它就会一直在那里。您的测试可以有一个条件,该条件获取该元素的 .text() 然后对其进行操作。如果您想单击其中一个,则可能看起来像这样。

cy.get('[data-cy=SectionLoaded]', { timeout: 10000 }).then(($loadedSection) => {
cy.get(`[data-cy=${$loadedSection.text()}]`).click()
Run Code Online (Sandbox Code Playgroud)

cypress.io 提供了更多相关信息,包括其他最佳实践和解决方法:


Jef*_*ner 3

@GrayDwarf:谢谢您的回复

我确实用过赛普拉斯contains

cy.get('div[data-cy="sales_listing_section"]')
    .contains(
        'h1.header-title[data-cy="sale_items_header"]',
        'Items for Sale',
        {timeout: 10000}
    )
    .then(() => {
Run Code Online (Sandbox Code Playgroud)

以及模块npm cypress-wait-until

cy.get('div.main-content')
    .then(($sectionBody) => {

        // @ts-ignore
        cy.waitUntil(() => {
            return ($sectionBody.find('div[data-cy="sales_listing_section"]').length > 0)
        }, {
            errorMsg: `ERROR: Sales section has not loaded.`,
            timeout: 10000, // waits up to 10000 ms, default to 5000
            interval: 500, // performs the check every 500 ms, default to 200
            verbose: true,
            customCheckMessage: `CHECK: If Sales section has loaded`
        })
            .then(() => {
                cy.log('Sales section', 'Loading finished');
            })
    })
Run Code Online (Sandbox Code Playgroud)

  • waitUntil 部分是很好的提示,我面临着反应重新渲染的问题,它解决了问题。 (2认同)