Why Cypress Sucks for Real Test Automation? (Part 2: Limitations)

Many limitations of Cypress makes it not suitable for serious test automation

Image for post
Image for post

I have received some positive feedback on my “Why Cypress Sucks for Real Test Automation article. A few readers wanted to clarify it a bit more. Yes, the article was more focused on why there is really no need to use Cypress, as there is a much better tool (in almost every way) Selenium WebDriver. In this follow-up article, I will focus on the limitations of Cypress.

1. Technical limitations of Cypress

For the specific technical limitations of Cypress, please read an excellent article “My Thoughts on Cypress.io” by Alister Scott on 2019–07–16. I will just highlight the comments section here:

and the reply from Alister Scott:

Gleb and Alister exchanged their opinion professionally. A top test automation engineer like Alister had problems testing iframes with Cypress, and the distinguished engineer at cypress confirmed it. For the wrong claim (“”) of Cypress, it is from Cypress’s marketing team, don’t take it seriously. One sure thing is, even Cypress die-hard fan would agree: Cypress has technical limitations.

Frames have been in HTML for as long as I could remember. For > 50% of projects (), I had to drive iframes with Selenium WebDriver, which was totally fine. About 2 years ago, a so-called ‘Cypress tester’ I met mentioned that he was unable to test frames or upload files with Cypress. I thought it was absurd! He simply lacked a basic understanding of test automation. That is, if unable to testing one operation on a web page, then it pretty much means the application cannot be tested. This is simply the nature of UI test automation.

To qualify for a web test automation framework, it shall not have serious technical limitations. This is common sense, isn’t it? After all, people will use it for verification. I never had ‘limited’ feeling with Selenium WebDriver.

I know some would argue: “I can do with cypress-iframe now (in 2020)”. Yes, it might be the case (frankly, I didn’t want to waste time to verify that after finding so many limitations with Cypress). Then, how about other limitations, such as not supporting multi-tabs, cannot visit two domains of different origin, only inside the browser, unable to drive two browsers, …, etc. For each of the above limitations, I had a case to use it in recent projects. With Selenium WebDriver, no problems at all.

Gleb Bahmutov, who is probably the man with the most Cypress knowledge on earth, acknowledged that “”. Will your project have ‘many years’ to wait? Unless you want only a fancy demo, do not use it for real test automation.

2. Cypress is actually slower

In Cypress’ documentation, it claims:

Image for post
Image for post

This is incorrect, at least no longer correct. Cypress test execution speed may be OK initially (suitable for a demo) but will get slower. Cypress is based on Chrome DevTools Protocol (CDP) which is a protocol developed to enable a debugger inside Chromium-based browsers. According to this article by Simon Stewart, the creator of Selenium WebDriver.

My personal experience confirmed this. According to this recent benchmark comparison by Giovanni Rago: Cypress was the slowest in most categories. For a very small test suite, Cypress is about the same or slightly slower than Selenium WebDriver. I expect Cypress will be considerably slower on a medium or large test suite. But test automation attempts with Cypress have probably failed long before reaching that size, as it is inefficient and difficult to maintain.

3. Cypress tests are hard to maintain

In test automation, the view of an inexperienced test automation engineer can be quite different from an expert. I have had extensive experience in maintaining a large scale of automated UI tests (referred to as an ‘expert’ on some software conferences’ brochures). I pioneered “Functional Test Refactoring” which was presented at STARWEST 2013, one of the longest-running and most respected conferences on software testing.

I will post a series of articles in the near future on test maintenance. Here I will just be brief with some key facts and questions:

  • Fact: The efforts to maintain automated UI tests is much larger than test creation
  • Fact: Real test automation means to keep your automated tests up with application changes that happen frequently
  • Fact: The audience of the automated test scripts are the whole team, not just programmers
  • Question: How do you score on “AgileWay CT Grading” (based on the test count, valid and frequently run ones)? My score is Level 3. For all Cypress projects that I knew of, Level 0. The №1 reason: ‘Cypress testers’ inability to maintain them.

4. Cypress can only use Node.JS, which is not suitable for test automation

JavaScript is good for web programming, not ideal for test automation. I will write another article on why we should avoid JavaScript in automated UI test scripts. FYI, I have been using JavaScript since the last century and had authored the book: “Selenium WebDriver Recipes in Node.js”.

Here I will just highlight three issues with Node.js for automated testing:

(1) Confusing JavaScript Promise

JS Promise is an async programming model, a complex concept. It can usually cause confusion. Above all, it is totally unnecessary for automated testing. A Node.JS programmer might say “”. Wrong! “It is not about you”. Automated functional test scripts shall be understandable to all the team members, including business analysts.

Here is a JS Promise example from cypress-examples by Gleb):

Try to find a business analyst to understand and use test scripts like the above.

(2) Unnecessary NPM package.json

The file package-lock.json is for a Node.JS project to manage dependencies. This makes sense for an app, but not much for automated tests. I have seen many people, myself included, often got this error when trying to run a Mocha test.

% mocha spec/01_login_spec.jsError: Cannot find module 'selenium-webdriver'

The library was installed, there was just no package-lock.json in the current directory. While the solution is simple: npm install, it is still quite troublesome.

In Ruby, there is a similar concept for library dependency management: Gemfile.lock, but it is optional and won’t affect test execution as long as your dependent libraries are installed on the machine. Easy!

(3) Large node_modules folder

Image for post
Image for post

npm install will create a node_modules folder, a cache for the external modules. For a minimal Selenium with Mocha test, its node_modules folder contains 3759 files/folders, 23MB on disk.

A common mistake is that engineers checked the node_modules folder into a Git repository!

With Ruby, there is no such mess at all.

5. Cypress wrongly added “retry-ability”, which shall be a CT feature

Cypress introduced Test Retries in v5 in August 2020, which is another step in the wrong direction. I came up with the idea of auto-retries in 2007 and have been used it ever since, but in CT server, not the test framework. Please read this article: “Why Auto-Retry of Test Execution in a Test Framework is Wrong?

6. Complex and Inconsistent Syntax

“Good syntax” is one of the main reasons that Cypress testers promote it. In my opinion, it is the opposite. Cypress syntax is inferior. To be fair, I will use the example in the Cypress Documation to compare against Selenium WebDriver.

Here is the Selenium + RSpec version:

I like Selenium’s version better, for the following reasons:

  • One line for one user operation, which will be very helpful for debugging test failures
  • It follows an intuitive pattern: “Find a control, then drive it”
  • Selenium does not have built-in assertion syntax. It leaves it to the test syntax framework. Therefore, the user has maximum flexibility. By the way, RSpec deprecated should assertion syntax () for expect instead, and I prefer expect .
  • There is no ambiguity in Selenium. Cypress is syntactic ambiguity. For example, Is cy.contains('type') for the text, button, link, or all of the visible text on the page? Or what happens if there are two links big type and type , which one will Cypress click?
  • The scope definition do to end () is better than () => { and }) ()

The above example is just Cypress in the simplest form. With a proprietary syntax framework, a common pattern is that complex and inconsistent new syntax with the updates. Here is a ‘Get retry attempts’ example.

it('does something differently on retry', { retries: 3 }, () => {     
// cy.state('runnable') returns the current test object
// we can grab the current attempt and
// the total allowed attempts from its properties
const attempt = cy.state('runnable')._currentRetry
const retries = cy.state('runnable')._retries
// use the "attempt" and "retries" values somehow

7. Not Future-Proof

For web test automation, with the only exception of Selenium WebDriver, all others are NOT future-proof. The simple reason is that only Selenium WebDriver is a W3C standard.

There are more Cypress/Puppeteer limitations I can go on. However, I will stop here, as the article is getting quite long now. I hope this article, together with Part 1, will convince you to switch to Selenium WebDriver which is far better in every way. If you tried Selenium WebDriver before and failed, you shall seek help from a good mentor.

Award-winning software developer, test automation & CT coach, author, and speaker. Help teams succeed with Agile/DevOps by implementing real Continuous Testing.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store