The most common mistakes in Cypress and how to avoid them

If you’re an IT tester and you use Cypress to test web applications, you’ve probably already encountered a number of specific challenges. This is not unusual, as testing is not a smooth ride. In this article, we’ll point out some of the common test-writing mistakes and offer advice on how to avoid them.

1. Mistakes associated with asynchronous behaviour

When working with Cypress, it is important to understand that many of its operations are asynchronous. Thus, the code does not wait for the operation to complete before proceeding to the next line. This can cause problems in tests because you may be trying to interact with elements that have not yet been loaded or changed.

 

To troubleshoot these issues, it is recommended to use Cypress commands such as cy.get(), cy.wait(), and cy.then(). These commands help manage asynchronous operations and ensure that you can rely on your tests.

1. cy.get()

This command is used to retrieve one or more DOM elements. cy.get() automatically waits for elements until they exist in the DOM.

Example:

<strong>cy</strong>.get('.button').click();

In this example, the user waits until the button with class .button appears in the DOM before clicking it.

2. cy.wait()

Cypress’s cy.wait() effectively addresses asynchronous behaviour in testing. It allows explicit waiting for network requests, such as AJAX calls, to complete by setting aliases and timeouts. With this approach, Cypress ensures that testing continues after the asynchronous processes are complete.

Example:

cy.intercept('GET', '/some-endpoint').as('networkRequest');
// Najskôr nastavíme interceptor na zachytenie požiadavky 
cy.wait('@networkRequest');
// Potom použijeme cy.wait() za účelom čakania na dokončenie tejto požiadavky

In this example, cy.intercept(‘GET’, ‘/some-endpoint’).as(‘networkRequest’) will first set up the interceptor to intercept a GET request for the endpoint / some-endpoint and assign it the alias networkRequest.

Then cy.wait(‘@networkRequest’) tells Cypress to wait for the request with the alias networkRequest to complete.

3. cy.then()

Cypress’s cy.then() is essential for dealing with asynchronous behaviour in tests. Its main role is to ensure that the code inside the callback function is executed only after all previous Cypress statements in the chain have completed. You can use cy.then() to retrieve the results of previous statements, which is useful for further validation or manipulation of the elements being tested.

Example:

cy.get('.message').then((element) => {
  // Priamo porovnávame text elementu s očakávaným textom
  expect(element.text()).to.equal('Očakávaný text');
});> {
 // manipulácia s položkami zoznamu
})

In this example, cy.get(‘.message’) first looks for an element with class .message. Then cy.then() is used to execute a function that takes that element as an argument. Instead of storing the element text in a variable, this example directly compares the element text to the expected text using expect().to.equal(). This method is efficient for verifying that the content of an element meets certain criteria.

2. Neglect of time limits

Cypress has its default timeouts for various operations, such as 4 seconds for cy.get(), cy.find(), cy.wait(), and others. It is important to know how these limits affect the behaviour of your tests.

You can customize the timeouts globally in the Cypress configuration file, which is typically cypress.json. This allows you to set limits that match the specifics of your application.

// Príklad nastavenia globálneho časového limitu v cypress.json
{
  "defaultCommandTimeout": 10000, // 10 sekúnd pre všetky príkazy
  "requestTimeout": 15000 // 15 sekúnd pre sieťové požiadavky
}

// V testovacom súbore
describe('Testovanie webovej stránky s nastavením časového limitu', () => {
  it('Testuje rýchle DOM operácie', () => {
    cy.visit('http://example.com');
    cy.get('.quick-element', { timeout: 5000 }).should('be.visible'); // Kratší časový limit pre rýchle DOM operácie
  });

3. Incorrect selection of elements

Incorrectly identified or overlooked elements lead to incorrect test results, which can mask defects or incorrectly mark functional parts as defective. This not only increases the risk of overlooking critical problems, but also leads to increased test fragility. Tests become prone to failure with minor changes in the application, requiring frequent revisions and increasing test maintenance requirements.

How to select elements in Cypress:

  1. Data attributes – It is recommended to use custom data attributes such as data-cy, data-test, or data-testid. This approach decouples the test selectors from CSS and JS, which increases the stability of the tests.
  2. Using Unique Selectors: if data attributes are not available, you can use CSS selectors. Try to avoid very specific or complex selectors that may be susceptible to design changes. Selecting elements by ID is also a good method as long as the IDs are stable and unique.

Example:

// Použitie data atribútov
cy.get('[data-cy=login-button]').click();

// Použitie unikátneho selektora
cy.get('#submit-button').click();

4. Not using custom commands

Many testers do not take advantage of the ability to create custom commands in Cypress. Custom commands allow you to centralize and reuse code, increasing efficiency and reducing the risk of bugs in tests. They allow you to have more consistent and easier to maintain test scripts. We have covered this topic in a special article Custom commands in Cypress.

Creating custom commands is easy and can greatly improve the readability and maintenance of tests. For example, if you frequently test logging into an application, you can create a login command that will do this for you.

// V súbore commands.js
Cypress.Commands.add('login', (email, password) => {
  cy.get('input[name=email]').type(email);
  cy.get('input[name=password]').type(password);
  cy.get('form').submit();
});

// V testovacom súbore
cy.login('user@example.com', 'password123');

This is just an example of how this concept can be used. By using custom commands, you can streamline testing and simplify the maintenance of your test scripts.

5. Insufficient test isolation

With the lack of test isolation in Cypress, you may encounter the problem of ambiguous and unpredictable results. If your tests are not sufficiently isolated, the result of one test may affect the result of another. This means that if one test changes the state of an application or database, it can cause subsequent tests to fail or pass, but not for the right reasons. It is important that each test is designed to be self-contained and independent of the others, so that your test results are more reliable and consistent.

How to achieve better test isolation in Cypress?

  1. Resetting the application state: at the beginning of each test, use commands like cy.visit() to reset the application state. This will help you start each test with a clean slate.
  2. Cleaning after tests: after each test, make sure that cleaning occurs. For example, remove test data to prevent it from affecting other tests.
  3. Use mocks and stubs: use mocks and stubs to simulate API calls or external services. This way your tests will not become dependent on external factors and the results will be more consistent. (Read also the Cypress API testing article.)
  4. Independent test scenarios: design your tests so that each is a stand-alone scenario that does not depend on the results of other tests. This ensures that each test is isolated and only verifies what it is supposed to.
  5. Read also about Cypress debugging tests.

Conclusion

Remember that every problem you encounter in testing is an opportunity to improve and learn something new. With these tips, you will be able to solve common problems you encounter when working with Cypress and increase the efficiency and reliability of your testing. Update your knowledge and don’t forget to visit the official Cypress documentation on the offcial website. Here you’ll find step-by-step tutorials and the latest updates to help you stay on top of software testing.

If you are a software tester and you speak German, take a look at our employee benefits and respond to our latest job offers.

About the author

Katarína Kučáková

Software Test Engineer

Moja cesta k testovaniu softvéru sa začala v roku 2019 až po štúdiu ekonómie a pracovných skúsenostiach v iných odvetviach. To mi pomohlo vnímať IT svet v rôznych súvislostiach. Ten totiž ponúka neustále nové výzvy, pre ktoré rada hľadám riešenia. Obľubujem oddych pri čítaní, turistiku alebo lyžovanie. LinkedIn

Let us know about you