Cypress: Slow assertion of a table

Created on 16 Apr 2020  ·  8Comments  ·  Source: cypress-io/cypress

Current behavior:

My Angular application displays some movies in a table which I assert using Cypress. My 20 row table takes 15 seconds to assert on my machine. You'll see Cypress basically hang and then resolve everything all at once.
Asserting 40 rows takes 50 seconds, so performance seems to deteriorate exponentially.

Desired behavior:

I'm sure Cypress should be able to do this more quickly.
If it's a programming error, I'd be interested to know what it is. I'm using aliases and a nested for loop.

Test code to reproduce

Use this repo to reproduce.
npm run e2e -- --watch to start Cypress, then click movies.feature.
The assertion code can be found here.
Worth noting I had a similar algorithm using then, which was almost equally slow.

Versions

Windows 10
Chrome 80

"cypress": "^4.4.0",
"cypress-cucumber-preprocessor": "^2.3.0",
performance 🏃‍♀️

Most helpful comment

You can avoid using aliases and get much faster speed, see PR example https://github.com/cypress-io/cypress-example-recipes/pull/487

If the table has "settled" and the individual values are not going to change, no need to access every cell individually

All 8 comments

I'm getting a lot of errors trying to run npm i on this repo. Any specific version of Node required?

Screen Shot 2020-04-17 at 5 26 56 PM

Are you familiar with .each()? It seems like you could maybe use that through some of these assertions.

But yes, basically for each .get() and each .find() Cypress runs through a series to checks, including checking visibility which can take some time. I think this is very similar if not the same issue as #6967 essentially, but I haven't been able to run the code directly.

I'm currently running Node v13.6.0 and NPM 6.13.4. Our build server runs Node 12, which also works.

Thanks, I've seen each, but haven't tried it out. I'll take a look if I can speeds things up using that.

Tried each. It's faster, 7 seconds for a 20 row table. Still not particularly quick.

I pushed a branch called cy_each that contains the modified code.

Fun fact: changing to the each solution makes my linux based CI build hang with Cypress 4.4.0, while I'm able to run the same on my Windows 10 machine without problems. Going back to 3.8.0 fixes that.

@jennifer-shehane What realistically are the chances for this to get priority to be fixed?

For my current project we'd like to shift from unit tests to stubbed e2e tests, but speed is of the essence for this as you can imagine. And we do a lot of table assertions in this application.
So we may have to decide not to shift or to try out protractor. Both not the solutions we're hoping for ;)

I got the tests running. This is likely identical issue as #6967, that the layout is recalculating due to us calculating visibility for every element you are iterating over.

You can see the 'timer' in the top of tests is locked up when it runs.

This issue isn't currently in our scope of prioritized work, so I couldn't give an estimate on when it would be addressed.

To reproduce

index.html

<html>
<body>
    <table>
        <tbody>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
            <tr>
                <td>Black Panther</td>
                <td>Ryan Coogler</td>
                <td>Marvel Studios</td>
                <td>2018-02-16</td>
                <td>97</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

spec.js

it('test', () => {
  const arr = ['Black Panther', 'Ryan Coogler', 'Marvel Studios', '2018-02-16', '97']
  cy.visit('index.html');
  cy.get('table tbody tr')
    .should('have.length.of', 20)
    .as('cyRows');
  for (let row = 1; row < 20; row++) {
    cy.get('@cyRows')
      .eq(row - 1)
      .find('td')
      .as('cyRowColumns');
    for (let column = 0; column < 5; column++) {
      cy.get('@cyRowColumns')
        .eq(column)
        .should('contain', arr[column]);
    }
  }
})

You can avoid using aliases and get much faster speed, see PR example https://github.com/cypress-io/cypress-example-recipes/pull/487

If the table has "settled" and the individual values are not going to change, no need to access every cell individually

@bahmutov Thanks, that makes a big difference!

I'm going to close this issue since you have a better workaround - particularly since the gist of the performance optimizations for Cypress are described in #6967

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zbigniewkalinowski picture zbigniewkalinowski  ·  3Comments

weskor picture weskor  ·  3Comments

brian-mann picture brian-mann  ·  3Comments

rbung picture rbung  ·  3Comments

verheyenkoen picture verheyenkoen  ·  3Comments