How to optimize Cypress tests using JavaScript abilities? (Part 1. Loops)
Tags: cypress, testing, javascript, typescript
Published: 2023-02-28 07:31:37

_Greetings to all Cypress enthusiasts!_

Those who have had experience working with [**Cypress.io**](https://www.cypress.io/) know that it is truly a wonderful tool that provides great opportunities for developing and implementing high-quality and reliable tests in your projects. Therefore, all that remains for us is to be able to make the best use of these opportunities.

The fact is that over the past few years, I have encountered various approaches to writing tests, sometimes with fundamentally different models and templates for building test scenarios and test cases. And it often happened that already written tests needed serious improvement or even complete restructuring, mainly to ensure their reliability and reduce the time it takes to run them. It’s obvious that as a QA engineer, it is crucial to continuously evaluate and optimize testing processes to ensure the highest possible level of quality assurance.

And in my observations, problems were often caused not only by a lack of deep understanding of the built-in commands of the testing framework, but also very often by an inability to apply _basic programming language capabilities_ in tests. This has prompted me to write a series of articles in which I share some of my techniques for optimizing Cypress tests, drawing on simple and mostly familiar JavaScript capabilities.

Among the most common errors, a separate group can be identified for cases where QA engineers repeatedly perform exactly the same actions on different elements, be it form fields, buttons, links, or any other UI elements. Often, depending on the tested elements or actions performed, they are often divided into separate tests. This leads to a sharp increase in the number of tests, which is further compounded by the presence of multiple prerequisites placed in _beforeEach_ and _afterEach_ hooks, which are repeated over and over again as test suites are executed. In some cases, such unjustified omissions ultimately lead to a significant increase in the overall time it takes to run tests.

In general, it is important to note that such erroneous actions do not correspond to the _DRY_ principle, which can make the tests harder to maintain, slower to run, and more prone to errors and inconsistencies.

Therefore, in the first article, I would like to discuss when and how the best way to optimize repeatedly performed actions, events, or assertions in Cypress tests using basic JavaScript **[loops](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration)** to avoid the above-mentioned ungrateful situations.

After analyzing the most frequently occurring cases of iterative actions during testing, I identified _8 common scenarios_ where the use of loops is most effective. This is certainly not an exhaustive list, as other cases may arise depending on the specified test scenarios. Next, I plan to examine each of these scenarios in detail and demonstrate with specific examples how loops can significantly help optimize your Cypress tests.

## 1. Iterating through a set of items or elements

When iterating through a set of items or elements, loops come in handy to perform repetitive tasks. For instance, if there are multiple checkboxes on a web page, a loop can be used to select or deselect each one of them. The loop can be controlled by setting the start and end values, making the code cleaner and efficient. By using loops in this scenario, you can ensure that all items or elements are verified or interacted with as needed.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23790enscf2g08ua5v5b.png)

In this example, we use the `Array.from()` method to convert an array-like object returned by Cypress `cy.get()` command to a standard array. We then use a `forEach()` loop to iterate over each element and perform some action.

## 2. Repeating a test with different inputs or expected outputs

For example, if there are multiple forms on a page, each requiring different inputs, a loop can be used to run the same test with each form. The loop can be controlled using conditional statements that verify the expected outputs for each input. This approach saves time and reduces the amount of code needed to test multiple scenarios.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1fiwurvwzdd7jpdci88.png)

In this example, we use a _**for…of**_ loop with _destructuring_ to repeat a test with different inputs and expected outputs. We define an array of objects, each with an input and expected output property, and use the loop to iterate over each object and perform the test.

## 3. Navigating through multiple pages

Cypress test can navigate through multiple pages of a web application by implementing a loop to check the contents of each page. The loop’s value can be regulated with conditional statements that confirm the existence of a next or previous page. Such a technique not only enhances the code’s organization but also improves its readability.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9knxxb926o2xsbwhsqfv.png)

This example demonstrates how to use `forEach()` loop to navigate through multiple pages. The code creates an array of page URLs, and then uses a `forEach()` loop to visit each page URL and assert that the page has loaded correctly using Cypress’s `should()` method.

## 4. Testing multiple user accounts or roles

If there are multiple roles or user accounts in a web application, a loop can be used to test each role or account by logging in with each set of credentials. The loop can be managed through conditional statements that confirm the anticipated results for every user role or account.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/se0nggyq0kawg8mlcsh9.png)

The value of using the **_for…of_** loop in this Cypress test is to execute the same test scenario multiple times with different sets of data. In this case, the test scenario is logging in with a specific user's credentials, performing some actions specific to their role, and then logging out. The loop iterates over the users array and performs the test scenario for each user in the array. This saves time and effort in writing individual tests for each user account or role, and allows for more efficient and comprehensive testing of the system under different user scenarios.

## 5. Running the same test with different configurations

If a web application has multiple configurations, a loop can be used to test the application with each one. The loop can be determined by implementing conditional statements that define the anticipated results for every configuration.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/08cmo6k8w36kwwhkd9zm.png)

The value of using the **_for…of_** loop in this test is to optimize the test execution by reducing code duplication. By iterating over the `configs` array and using the configuration data to set up the testing environment and execute the tests, we can avoid repeating the same setup and test code for each configuration.

This not only makes the test code more concise and easier to read, but it also reduces the risk of errors and omissions that can occur when copying and pasting test code. Additionally, by separating the configuration data from the test code, we can easily add or remove configurations without having to modify the test code.

## 6. Dynamically generating test data

Loops can be used to generate test data dynamically. For instance, if there is a need to create multiple user accounts, a loop can be used to generate a set of user data with each iteration. The loop can be controlled by setting the start and end values and by specifying the number of users to create.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94s98d8hphj4lw0zeeev.png)

The `forEach()` loop is used here to iterate over each key in the `testData `object and perform a test for each input. This loop enables the code to avoid duplicating the same test case for each input, and instead, it performs the same test for each input dynamically, thus saving time and effort.

By using a loop to iterate over the `testData `object, it becomes easy to add more test cases without duplicating code. This makes the code more efficient and reduces the likelihood of errors when adding new tests.

## 7. Iterating through a set of test steps

Also, loops can be used to iterate through a set of test steps when testing a web application. For example, if there are multiple steps involved in testing an application, a loop can be used to repeat the steps with each iteration. The loop can be managed using conditional statements that specify the expected outputs for each step.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6sr5qakx536kxqylh4h.png)

In this Cypress test each step is an object that contains information about an action that needs to be performed during the test, such as clicking on a button or typing into an input field. By using a loop `forEach()` to iterate through the steps array, the test can perform each action sequentially and with less duplicated code.

Inside the loop, the test checks the action property of each step object to determine what action should be performed. Depending on the value of action, the test will use a different Cypress command to perform the action. For example, if the action is click, the test will use the `cy.get().click()` command to simulate a button click.

## 8. Testing the same functionality or behavior across different environments

Loops can be used to test the same functionality or behavior across different environments, such as multiple screen resolutions or browser types. For example, if a web application needs to be tested on different browsers or screen resolutions, a loop can be used to test the application on each configuration. The loop can be controlled using conditional statements that verify the expected outputs for each environment.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6ibamf74tgwbq995yvc.png)

Inside the loop, the test sets the viewport size using the `cy.viewport()` command to match the width and height properties of the current environment. Using a loop in this way allows the test to be run multiple times with different configurations, without having to duplicate the same test code. This can make the test more efficient and easier to maintain, especially when there are many different environments to test against.

## Conclusion

Thus, we have confirmed that there are numerous useful applications of loops in Cypress tests, significantly improving testing efficiency, reducing the time spent on test runs, and enhancing test coverage. Overall, loops are an important tool for automating testing in Cypress, improving the process and saving time and effort. In our next articles, we will explore other JavaScript features that can help optimize your Cypress tests.

The source code of all presented examples can be found in the corresponding [_repository_](https://github.com/Sanzhanov/Cypress-tests-optimization) on GitHub.

_Thank you for your attention! Happy testing!_