10 best practices for successful Cypress automation testing


Cypress is a powerful testing tool that simplifies the process of test automation and offers the capability to develop stable and reliable test scripts. The tool allows developers to write tests using an intuitive and straightforward syntax, which makes it easy to create, run, and debug tests.

However, with this power and simplicity comes an essential responsibility – following the recommended best practices for Test automation. The Cypress team places a significant emphasis on these practices to ensure that users can develop and maintain robust and dependable test scripts.

Failure to adhere to these best practices can lead to unstable tests that produce unreliable results. This can be particularly challenging for developers who are trying to diagnose and resolve issues with their testing framework, which can require a significant amount of time and resources to fix.

By following the best practices recommended by the Cypress team, developers can ensure that their tests are stable, reliable, and low-maintenance. These practices cover a range of topics, including test organization, test data management, test suite configuration, and more.

What is Cypress?

Cypress is a widely used testing framework that has gained popularity for its open-source nature and user-friendly features. It is primarily used for testing web applications, as it allows developers to write tests in JavaScript that can be run directly in the browser.

It has an intuitive and easy-to-learn syntax that makes writing tests a breeze. This, coupled with its fast and reliable execution, has made it a popular choice for developers who value speed and accuracy in their testing efforts.

To achieve optimal results when using Cypress, it’s essential to be aware of and follow the best practices. Here are 10 best practices that you should keep in mind when using Cypress.

  1. Using data attributes during the selection of cases
  • This approach involves adding unique data attributes to elements in your application’s HTML markup and using those attributes as selectors in your tests.
  • By using data attributes as selectors, you can create tests that are entirely independent of your application’s CSS or JavaScript. This is important because even minor changes to your application’s styling or functionality can cause selectors based on CSS or JavaScript classes and IDs to break, rendering your tests ineffective.
  1. Use of dynamic waits

When writing code for page actions such as visiting a URL, saving, updating, or deleting data, some developers use the cy.wait(timeout) command to pause the script until the API is active and returns the expected results. However, using a static wait command like this is not recommended, as it can cause unnecessary delays in your test suite. If the page loads in just two or three seconds, the script will still wait for the full five seconds before proceeding to the next step, which can lead to slower test execution times.

To address this issue, it’s recommended to use dynamic wait commands that wait for specific events to occur before proceeding to the next step in your test code. Dynamic waits are more efficient and reliable because they respond to the actual behavior of your application.

For instance, instead of using cy.wait(timeout), you can use the cy.get() command to wait for a specific element to appear on the page before continuing, 

By using dynamic waits like this, you can create more efficient and reliable tests that respond to the actual behavior of your application, and avoid unnecessary delays.

  1. BaseUrl in the config file

Adding BaseUrl in the config file ensures that all spec files use the same base URL without the need to hard code it in each file’s before() block. This approach simplifies the test code and improves its readability and maintainability.

Moreover, using the baseUrl property in the cypress.json configuration file allows you to define environment-specific URLs. For instance, you can set different URLs for development, testing, and production environments by using separate configuration files for each environment. You can also use environment variables to set the base URL dynamically based on the environment the tests are running in.

  1. Specifying “scripts”  in package.json

When working with Cypress, it is common to use the terminal in Visual Studio Code to run commands. For example, the command “cypress open” is used to launch the Cypress runner. However, it is recommended to define this command in the “scripts” section of the package.json file.

By defining the “cypress open” command as “npm run cy:open” in the “scripts” section, developers can easily execute it in the terminal using the user-defined name. The “scripts” section allows developers to define all the commands that they use to run in the terminal, and it offers the advantage of creating user-defined names for lengthy commands. This makes it easier to remember and execute the command later without having to type out the full command every time.

  1. Avoid using single assertions

It is recommended to avoid using single assertions when writing E2E tests. While single assertions may be suitable for unit testing, they may not be the best approach for E2E testing. Even if you don’t divide your Cypress assertions up into multiple test phases, you will still be able to identify the specific assertion that failed.

Instead of using single assertions, it is recommended to group assertions together in a single test. This will ensure that Cypress runs lifecycle events between your tests that reset your state, which is important for the effectiveness of your test suite.

  1. Servers operated by a third-party provider

Sometimes, your application can have an impact on another application that is developed by a third-party. Although this situation is infrequent, it is still a possibility that you need to consider.

As an illustration, you can integrate your application with GitHub to enable users to modify data inside of GitHub using your application. This means that when a user interacts with your application, it will trigger some changes in GitHub as well.

When it comes to interacting with GitHub’s APIs, you have the option of using cy.request() to communicate programmatically with the APIs after your tests have finished running. This technique eliminates the need for you to ever interact with another application’s user interface. 

By using this approach, you can avoid any potential issues that may arise from relying on another application’s user interface to function properly. This will make your application more robust and less prone to failure.

  1.  Expressing control state through programming

To ensure proper testing conditions, it is recommended to set the application state programmatically whenever possible, rather than relying on the UI. This decouples the UI from the application state and can result in improved performance since programmatic state setting is faster than UI interaction.

For example, instead of using the UI to log in a user as shown in the code sample above, we can use cy.request to communicate directly with an API to perform the login. This approach can also be applied to other actions, such as adding test data to the application to set it in the desired state.

  1. The cy.clock and cy.tick commands provide you with the ability to manipulate the flow of time during the execution of your tests

These commands can prove particularly useful in scenarios where you need to test features that are time-dependent.

With the help of cy.clock and cy.tick, you can accelerate the execution of your tests by skipping over prolonged waiting periods. This can help you speed up your test runs and get faster feedback on the performance of your application.

By making use of these commands, you can precisely control the timing of your test cases, allowing you to simulate various time-related scenarios with ease. This way, you can accurately test how your application behaves under different conditions, such as network latency, animation timings, or time-sensitive functions.

  1. The cy.visit command is a powerful tool that can help you optimize the performance of your test suite

One of the main benefits of using this command is that it allows you to selectively load only the necessary resources for your test cases.

In situations where you don’t require certain resources, such as images or external JavaScript files, loading them can take up valuable time and slow down your test runs. By using the cy.visit command to specify only the resources you need, you can bypass the loading of unnecessary resources and speed up your test runs.

This feature is especially useful for large and complex applications that may contain many resources, as loading unnecessary resources can cause significant delays in the execution of your test cases. By using the cy.visit command to optimize resource loading, you can achieve faster feedback on the performance of your application and speed up your testing process.

  1. The cy.load command can help you optimize the performance of your test suite by pre-loading frequently used resources. 

By pre-loading resources, you can reduce the amount of time it takes to access them during the execution of your test cases, resulting in faster test runs.

If your application relies on resources that are used frequently, such as images or external JavaScript files, loading them repeatedly can take up valuable time and slow down your test runs. However, by using the cy.load command to pre-load these resources, you can ensure that they are available for immediate access whenever they are needed, reducing the time it takes to access them and improving the overall performance of your tests.

LambdaTest is a cloud-based platform that offers both exploratory and automation testing capabilities for web applications. With LambdaTest, you can perform cross-browser testing of your Cypress tests on a variety of different browsers, operating systems, and devices, which can help to improve the overall quality and reliability of your tests.

Moreover, LambdaTest provides a range of additional features, including screenshot testing, network throttling, and real-time testing, to further enhance the accuracy and reliability of your Cypress tests. Furthermore, it also offers a debugging feature that allows you to debug the code in real-time, enabling you to quickly identify and resolve any issues that may arise.


Following best practices or rules is essential to ensuring the success of your testing efforts. By adhering to established standards and guidelines, you can minimize potential challenges and streamline the testing process.

One of the key benefits of using best practices is that they can make your life as a QA automation test engineer much easier. Following these guidelines can help you create more efficient and effective test scripts, reduce the likelihood of errors, and ensure that your tests provide accurate and reliable results.

Back To Top