How To Avoid Anti-Patterns In Cypress


Posted On: April 13, 2022

view count58472 Views

Read time12 Min Read

No matter how advanced your automation technology is, anti-patterns represent standard bad practices, code smells, and pitfalls. In this case, when creating automated tests, teams can experience a range of difficulties that compound to create inefficient, incomplete, and hard-to-maintain tests.


In addition, to provide high-quality, cost efficiency, and on-time delivery, it’s essential to recognize the signs that your tests aren’t performing optimally. In this Cypress tutorial on avoiding anti-patterns in Cypress, we will discuss some anti-patterns that we believe should be avoided using Cypress test automation framework for the most relevant testing experience and end product.

Let’s get started!

Get the best out of your Cypress tests with LambdaTest’s online Cypress automation tool. Check out how you can test your Cypress testing scripts using LambdaTest’s online cloud.

Fragile Locators

Have you experienced fragile locators in your test scripts? Any slight change on the UI would fail the tests, and it will require some maintenance work to update the specific locator.

Imagine a dynamic CSS, XPath, Id, Class, Tag selectors; it could be tough to target elements changing every time the web page loads.

target elements

Let’s imagine an input field

The easiest way to approach could be using:

But, that wouldn’t be the best approach as this is a fragile selector; instead, we should add test attributes to our elements, and the example above it should be like the following:

Now, we can use our locator in a better way:

The test-cy attribute will not change from CSS style or JS behavioral changes; additionally, it clarifies to everyone that this element is used directly by the test code.

Also readHow to Find HTML Elements Using Cypress Locators

Overcomplexity, chains in Cypress

We always want to use elegant solutions and apply a better approach in our test automation code, but always remember the KISS principle; if you are not aware, KISS is an acronym for Keep It Simple, Stupid. This principle says about making your code simple. It will help if you avoid unnecessary complexity. A simple code is easier to maintain and easier to understand.

Chaining the .type() onto the cy.get(), telling it to type into the subject yielded from the cy.get() command, which will be a DOM element.

Using Aliases, let us reuse our DOM queries for faster tests when the element is still in the DOM. Furthermore, it automatically handles re-querying the DOM when it is not immediately found in the DOM. It is beneficial when dealing with front-end frameworks that do a lot of re-rendering.

Another cool thing about Cypress is the built-in retry function available in too many commands; there is a default timeout set to 4000 milliseconds, which you can modify in your cypress.json file. If you come from Selenium, you probably know it as a fluent wait. In this case, nothing extra needs to be added to our tests to make them wait fluently.

Also readCypress Vs Selenium: Which is Better in 2022?

Inefficient waits, avoiding waits in Cypress

Perhaps, you want to debug your tests, or you need to halt your tests for a couple of seconds to see the desired state. But, in Cypress, when you use .wait() and do nothing for a couple of seconds, how long do we need to wait? We understand sometimes our test scripts are going so fast that we need to consider hard waits and tell Cypress to reduce speed. But remember using waits in our code is regarded as an anti-pattern in Cypress.

Instead, we can use timeout per command; the timeouts can be modified per command, which will affect all default assertions and any assertions chained after that command.

Also, you can wait for basically anything by passing a callback function into the .should() command. It will use the built-in retry logic and wait for the procedure to pass. As a recap in our example above, Cypress will wait 5 seconds for the element to exist in the DOM and wait another 5 seconds for the same element to be visible.

Optimizing DRY, custom commands in Cypress

If you are not aware of custom commands in Cypress, it is an excellent time to avoid reinventing the wheel and reuse those available custom commands. Cypress comes with its API for creating custom commands and overwriting existing commands, for example, cypress-downloadfile:

You can install the module:

Then, add the following line to cypress/support/commands.js:

Add the following lines to cypress/plugins/index.js

After we can start using the custom command the following way:

As mentioned before, we can reuse most of the custom commands, but Cypress allows us to modify the behavior of these custom commands; this is really useful to optimize our code and use the DRY principle.

Let’s try not to overcomplicate things and reuse custom commands in our tests.

In the below Cypress testing tutorial video, you’ll understand how to create custom commands in Cypress.

You can also Subscribe to the LambdaTest YouTube Channel and stay updated with the latest tutorials around automated browser testing, Selenium testing, CI/CD, and more.

Behavior Driven Development in Cypress

Behavior-driven development is a software engineering practice developed to deliver high-quality products by focusing on the business value or behavior of the system. The main difference is BDD focuses on the behavior/ business value. In contrast, TDD focuses on tests which sometimes leads developers to become too detail-focused compared to the business focus/value. However, it’s important to understand the TDD vs BDD difference before choosing a suitable framework.

Cucumber is a tool that supports BDD; anyone can write specifications in plain English using Gherkin. It is as simple as adding a test from the business value point of view, as I like to call business-centric test automation.

Let’s start adding the cucumber plugin using npm to our current Cypress project. Please follow the below video for Cypress installation:

Please install the plugin.

The following dependency with the latest version will be added to your package.json of the project. At the time of writing this recipe, the version of cypress-cucumber-preprocessor is 4.1.4

To make it work, we would need to add it to cypress plugins as part of Cypress Configuration under cypress/plugins/index.js

Next, we need to add cosmiconfig configuration to the package.json. Cosmiconfig searches and loads the required configuration of the project. In this case, we are defining to locate the step definitions by setting up the below property.

Let’s create a new folder under Cypress -> Integration directory as ‘cucumber-test’ and then create a new feature, “Home.feature.”

For step definition location, let’s create a folder named “home.”

Let’s create a step definition file ‘homeSteps.js.”

The folder structure should be as the following:

folder structure

Now, let’s run using the following command in the terminal or command console to execute the test:

On Cypress Test Runner, select ‘home.feature’


And you should see the results correctly:


Also readNow Run Your Cypress Tests on LambdaTest

Cucumber Expressions

In the “.feature” file, cypress-cucumber-pre-processor uses the same expression as the cucumber expressions to link Gherkin to step definition. This can be achieved either by Cucumber expressions or regular expressions. The advantage of these is that they are more humanly readable than regular expressions. The following is how a Gherkin Step is translated in Step Definition.

Gherkin Step

Step Definition translation

Gherkin Keywords

Keywords are used to give structure & meaning to the executable specifications. For example, every specification or a feature file starts one of the keywords as:



Step definition will look like the following:

Cypress 101 Certification

Take this certification to showcase your expertise with end-to-end testing using Cypress automation framework and stay one step ahead.

Here’s a short glimpse of the Cypress 101 certification from LambdaTest:

Gherkin Functions

Gherkin uses functions to execute the specifications/ features files. These functions are used to translate the specification to executable tasks with the help of expressions or regular expressions.

  • GIVEN represents pre-conditions in the executable specification. It is a pre-step to the specification or test.
  • WHEN represents the condition in the executable specification. It is a condition to the specification or test.
  • THEN represents post-condition in the executable specification. It is the post-condition to the specification or test. There could be single or multiple steps as part of Then (post-condition).
  • AND step is to extend pre-step, conditions, and post-condition (s). It can be used with all the functions (Given, When & Then).
  • BUT is helpful to define the negative step in the scenario. Same like AND step, BUT also supports the Given/When/Then step.

How do you write a feature statement?

Follow the following principles to build greatness in features.

  • Keep it short and to the point.
  • Make your benefits measurable.
  • Emphasize the advantages.

The principles are not mandatory like Gherkin Keywords or Function, but they communicate the vision or goal of the feature.

Feature and Steps Definition

Here, we can find our Feature File and our Step Definition file.

File: search.feature

File: search.feature

File: searchSteps.js


Code Walkthrough

Let’s start defining our Page file, here we can include our locators and URLs:


We defined the URL, in this case, LambdaTest Playground, and our search locator, as we can see in the following two methods:

Now, let’s take a look into our Step Definition file searchSteps.js.

First, we need to import our Cucumber plugin previously installed and our SearchPage file; this file includes our selectors and methods.

Now we need to define our Given, When, and Then steps; let’s start with the “Given” one:

As we can notice, we are calling our SearchPage method to perform a “cy.visit”.

Related to our “When” definition, we take advantage of dynamic parameters coming from our feature file. Therefore, it is helpful to get the actual search value from the feature file.

As we notice, we are distinguishing from a search returning any Product vs. a search returning no Products; it is helpful as our feature can include negative scenarios.

And here is the test execution, which indicates that our BDD approach is working:

BDD approach


How to run Regression on Cypress Cloud Grid

We can use a Cloud Cypress Grid like LambdaTest, which provides automated cross browser testing on 40+ browsers and operating systems, and Cypress parallel testing to expedite the test execution in a scalable way. In addition, it will help improve our overall test coverage by resulting in better product quality as we can cover different combinations using the same test scripts.

To get started with Cypress testing, you have to install LambdaTest Cypress CLI on your machine. Trigger the following command to install the same:

After installation is completed, set up the configuration using the below command:

Once the command is completed, lambdatest-config.json is created in the project folder. Next, enter the LambdaTest credentials from the LambdaTest Profile Section.

Here is how you can configure the required browser & OS combinations in lambdatest-config.json:

The run_settings section in the JSON file contains the desired Cypress test suite capabilities, including Cypress_version, build_name, number of parallel sessions, etc.

Tunnel_settings in the JSON file lets you connect your local system with LambdaTest servers via an SSH-based integration tunnel. Once this tunnel is established, you can test locally hosted pages on all the browsers currently supported by Cypress on LambdaTest.

Now that the setup is ready, it’s time to run the tests; remember that our run_settings file displays the parallels field as five once we trigger our execution in parallel without any extra parameter.

Shown below is the test execution status from the LambdaTest Automation Dashboard.

LambdaTest Automation Dashboard

To view test performance metrics, navigate to the LambdaTest Analytics Dashboard. The Test Overview will provide a snapshot of tests consistent with stable behavior. Meanwhile, the Test Summary will display the total number of tests passed or failed, as well as any completed tests and pending tests.

LambdaTest Analytics Dashboard

Also readHow to Perform Cypress Testing at Scale with LambdaTest

Final Thoughts

The presented list was not supposed to be exhaustive since there are good resources and smells/patterns in Parts II and III of xUnit Test Patterns. In this Cypress e2e testing tutorial on avoiding anti-patterns in Cypress, I focused on the BDD approach as our Test Automation must be customer-centric and easy to follow from our non-technical stakeholders.

Happy Bug Hunting with Cypress!

Frequently Asked Questions (FAQs)

Is Cypress better than Selenium?

Cypress is considered to be a more developer-friendly web testing alternative to Selenium or Protractor. Although Cypress is new on the scene, it is quickly catching up with Selenium. It has good documentation and a large community mostly centered around user story tests.

How can I improve my cypress performance?

1. Write one test rather than multiple tests.
2. Remove unnecessary disk I/O by tweaking Cypress’s configuration.
3. Only Tag and Run the tests that you need.
4. IncludeCypress into your CI/CD, etc.

Should Cypress tests be independent?

Cypress runs tests in parallel. All tests can run independently from one another, making the code more testable, reliable, and maintainable.

Author Profile Author Profile Author Profile

Author’s Profile


Enrique DeCoss, Senior Quality Assurance Manager at FICO is an industry leader in quality strategy with 16+ of experience implementing automation tools. Enrique has a strong background in Testing Tools, API testing strategies, performance testing, Linux OS and testing techniques. Enrique loves to share his in-depth knowledge in competencies including, Selenium, JavaScript, Python, ML testing tools, cloud computing, agile methodologies, and people Management.

Blogs: 11