There are many ways to measure performance. In today’s post I want to talk about one of the most simple. Imagine a following scenario:
Our test may look something like this:
This modal window may fetch some data from server, reorder or filter it. Additionally it may perform some other actions such as render images etc. All of these actions take some time and as testers, we want to make sure that the result will not take too long.
In all of the current browsers a
performance API is available on
window object. We can access this API by using
cy.window() function and then calling a method. To start measuring the performance, we can create a mark that will label the start of our measurement.
The highlighted part of our code does actually the exact same thing as if we were to type
window.performance.mark('modalOpen') in our DevTools console. The
modalOpen is just a label, and can be named anything.
Now that we have labeled the start of our metric, let’s perform the next steps. When we click on the card, it opens modal window. First, we want to make sure that we have reached the desired result. We can check that by making an assertion on the modal window visibility:
After that, we can call
performance.measure()function to make our measurement. Basically, we are pressing a button on a stopwatch here. The argument of the
measure function will be our
modalOpen label. The reason for passing this argument is that we can actually add multiple labels into our test and we need to specify which one to measure. To call the measure function we basically perform a very set of Cypress functions as before:
The invoke command is going to yield an object with all kinds of results:
Within this command, we can pick a property from this object using
.its() command. Since we don’t need retryability, we can set timeout to 0 and make our assertion immediately. Let’s make an assertion that the modal should not load longer than 2 seconds (2000 in milliseconds).
Now that we know what to do, we can create a custom command out of this. There’s a lot of TypeScript going on, so let me break down what’s happening here. Lines 1-9 is a type declaration. This is how we tell TypeScript compiler that we have added a new
cy.mark() command to the library of
cy commands. The library is called
Chainable, and contains all
cy commands. This library is part of a bigger whole -
Lines 11 - 29 is a function that contains our chain of commands from previous example. In addition to that, I have hidden the logs of our three commands and added my own log which you can see on lines 15 - 24.
Finally, on line 31, we are adding this function to the Cypress library. While lines 1-9 add our command to the Cypress namespace that our TypeScript compiler can recognize,
Cypress.Commands.addAll() function will add it to the Cypress itself. I usually store my custom commands to
cypress/support/commands/ folder and do an
import ../commands/mark.ts inside
Similarly, we can add the
cy.measure() command as well:
A small difference from our
cy.mark() is that this time our return type will be
number, because the our function will return a number. Also, instead of using
.its() function, we are returning it from
.then() function as we want to use it in our console command detail as well. If this is a lot of new terms, I suggest checking out this post about improving custom Cypress command I’ve made earlier.
Whenever we do performance testing of any kind, we need to pay close attention to the environment we are testing on. Are we in production? Is it currently under heavy load? If on staging server, is it 1:1 with production or are we testing a scaled down version? Are we using browser for perfomance testing? Which one? Which version? All of this and more questions need to be asked to provide context for the performance metrics.
In our context, we are running inside a browser that has two iframes opened. One for our application and one for Cypress script. This may have effect on our testing and it is not slight. Cypress docs warn about this in their docs. This doesn’t mean that measuring performance in Cypress is useless. It just means that we need to take the context into account when looking at the metrics.
From time to time I send some useful tips to your inbox and let you know about upcoming events. Sign up if you want to stay in loop.