So why Cypress?
Moving on to the essence of the article, I would like to note that among the most common mistakes when writing Cypress autotests in a separate group, there are cases in which the same or similar actions, checks, conditions, etc. are repeatedly reproduced in tests. At the same time, depending on the elements being tested or the actions performed, they are often separated by testers into separate autotests. This leads to a significant increase in the number of tests, which is exacerbated by the presence of several additional conditions placed in
afterEach hooks that are played before/after each test as the test suites are executed.
In general, such situations do not correspond to the principle DRYcomplicate the maintenance of tests, slow down their execution, increase the likelihood of errors and flaky tests. In some cases, such errors eventually lead to a multiple increase in the total test run time.
After analyzing the most common cases of reproducing iterable actions when testing web applications, I highlighted 9 most common caseswhen using loops in autotests is most effective. Of course, this is not an exhaustive list, other cases are possible depending on existing test scenarios. Let’s take a closer look at each of them and use specific examples to learn how loops can greatly help optimize your Cypress autotests.
1. Iterating over a set/list of elements
Loops can be useful when iterating through a set of elements or a list of objects to perform repetitive tasks. For example, if a web page has multiple elements like checkbox, then a loop can be used to select or deselect each of them. The loop can be controlled by setting start and end values. Using loops in a scenario like this ensures that all elements or objects are iterated over as needed.
In this example, we use the Array.from() method to convert the value returned by the Cypresscy.get() command to a standard array. We then use a forEach() loop to loop through each element and then perform some action.
2. Repeating the test with different inputs or expected results
If there are multiple forms on the page, each requiring different inputs, you can use a loop to run the same test with each form. The loop can be controlled with conditional statements that check the expected result for each input value. This approach saves time and reduces the amount of code required to test multiple scenarios.
In this example, we use a for…of loop with destructuring to iterate a test with different inputs and expected results. We define an array of objects, each with input and expectedoutput properties, and use a loop to iterate over each object as the test runs.
3. Multi-Page Navigation
In a single Cypress autotest, you can navigate through multiple pages of your web application with a loop that checks the content of each page. The meaning of the cycle can be adjusted using conditional statements that confirm the presence of the next or previous page. This technique not only improves the organization of the code, but also improves its readability.
The example provided shows how to use a forEach loop to navigate through multiple pages. The code creates an array of page URLs and then uses a forEach loop to visit each URL and check that the page loaded correctly using Cypress’s should() method.
4. Testing multiple user accounts or roles
If a web application has multiple user accounts or roles, a loop can be used to test each role or entry, ensuring that you log in with different sets of credentials. The loop can be controlled through conditional statements that assert the expected results for each user role or account.
The point of using the for…of loop in the above Cypress test is to iterate through the array of users and run the same test case with different datasets. In this case, the test script involves logging in with specific user credentials, performing actions specific to their role, and logging out. This saves time and effort when writing separate tests for each user account or role.
5. Running the same test with different configurations
If a web application has multiple configurations for different runtime environments, then loops can be used to test the application in each of the specified runtime environments.
Using a for…of loop in this test allows you to optimize test execution by reducing code repetition. By looping through the config array and using the configuration data to set up the test environment, we can avoid repeating the same code when writing tests for each configuration.
This makes the test code more concise and understandable, and also reduces the risk of possible errors. Also, by separating the configuration data from the test code, we can easily add or remove configurations without having to change the test code itself.
6. Dynamic generation of test data
Loops can be used to dynamically generate test data. For example, if multiple user accounts need to be created, a loop can be used to generate a set of user data at each iteration. The cycle can be controlled by specifying start and end values, as well as specifying the number of users to create.
The example uses a forEach loop to iterate over each key in the testData object and run a test for each input. This loop avoids duplicating the same test case for each input by running the same test dynamically for each input, and it’s also easy to add new test cases. This makes the code more efficient and reduces the chance of errors when new tests are added.
7. Iterate over a set of test steps
When testing a web application, if a test case includes multiple steps, a loop can be used to repeat those steps at each iteration. In this case, the loop can be controlled using conditional statements that indicate the expected result for each step.
In this test, each step is essentially an object that contains information about an action to be performed during testing, such as clicking a button or entering specific text in an input field. By using a forEach loop to iterate through an array of steps, the test can perform each step sequentially and with less repetitive code.
Inside the loop, the test checks the action property for each step to determine which action should be taken. Depending on the value of the property, the test will use a different Cypress command to perform the action. For example, if the action is type, the test will use the cy.get().click() command to simulate a button click.
8. Testing the same functionality or behavior in different environments
If a web application needs to be tested on different browsers or screen resolutions, a loop can be used to test the application in each configuration. The loop can be controlled with conditional statements that test the expected results for each environment.
So, in the above example, inside the forEach loop, the size of the viewport is set using the cy.viewport() command with the width and height parameters being changed. Using a loop in this case allows you to run the test multiple times with different configurations without duplicating the test code. This makes the test more efficient and easier to change, especially when you need to test many different environments.
9. Waiting for an element to appear
Loops can be used to wait for an element to appear on a web page for n times. For example, if your web page has a loading spinner that appears multiple times during different interactions, you can use a loop to wait for the spinner to disappear each time it appears. The cycle can be controlled by setting a maximum wait time or by specifying a condition that signals the end of the cycle.
In this example, we use a while loop to repeatedly check if an element with id element exists on the page. The loop will keep running until either the element is found or the maximum number of retries is reached. Using a loop is important because it allows us to handle situations where an element might not appear on the page right away, or where network or server delays might cause the element to appear only after a certain amount of time. Without a loop, our test might fail if the element is not found on the first try, even if the element eventually appears on the page. However, I will not argue that the use of a cycle in the above case is the best practice of the possible solutions.
Thank you for your attention and happy testing!