WebdriverIO vs. Cypress: Which Is Better To Use in 2023?

Software development
WebdriverIO vs. Cypress: Which Is Better To Use in 2023?

In the world of software testing, it is well-known that Cypress and Selenium are hot topics. However, in this blog post, we are going to take a closer look at another testing framework: WebdriverIO, and compare it to Cypress.

Cypress and WebdriverIO are both popular tools for automated web application testing, and both have advantages and disadvantages. Basically, the choice between them depends on your specific needs and requirements. While WebdriverIO has existed for quite a long time, and over the years, it has evolved, adding necessary new features, Cypress is a few years younger.

Automated web application testing

In the following paragraphs, we’ll contrast Cypress with WebdriverIO, provide a few examples for you to get a feeling of what it’s like in the trenches, and examine which tool is better for your situation. Also, we will mention WebdriverIO a little bit more this time. So, let’s get going!


Cypress is a framework for web test automation that assists programmers and testers in producing JavaScript-based web automation scripts. The choice to adopt JavaScript as the final product was certainly influenced by the fact that JavaScript is one of the most popular languages. Because developers around the globe use JavaScript, it improved the chances of wide adoption of Cypress by the developer community.

The Cypress automation framework includes these stages, just like other web automation frameworks:

  • Create tests > script them > run them > and then debug them.

WebdriverIO and Cypress are frequently compared. However, Cypress has a different design. Compared to WebdriverIO, it has fewer limits. Using Cypress enables you to quickly and easily construct your automation web scripts. The major difference between the two is that Cypress works directly in the browser, while WebdriverIO uses API drivers to communicate with the environment that the app runs on or in, e.g., the browser.

In short, anything running in a browser can be tested with Cypress. So, we can use Cypress to automate the following categories of testing:

  • Unit testing
  • Integration testing
  • End-to-end testing

Since Cypress is distributed as an npm package, it is very easy to install and configure; we only need the following two commands to get started.

npm init
npm install cypress --save-dev

The first command creates an empty package.json file. The second command installs Cypress and all necessary dependent packages. Therefore, we don’t have to install each and every dependency separately as one had to do in the case of WebdriverIO. 

Basic example

Cypress has very easy-to-understand syntax because it uses JS, and everything is wrapped within the describe block.

describe('Test suite'), function () {
   it('search navigation on web page', function () {
       cy.title().should('include', 'Outwit the Challenge')
}Code language: JavaScript (javascript)

Cypress component testing

From version 10+, Cypress supports component testing. The main difference from the standard mode of operation is that Cypress Component Testing builds your components using a development server instead of rendering within a complete website.

This results in faster tests and fewer dependencies on infrastructure than end-to-end tests covering the same code paths. It allows you to focus on testing only the component’s functionality and not worrying about other nuances with testing a component as part of the larger application. There are many tools for this section to compare, but that’s out of the scope of this blog.


WebDriverIO (or wdio in short) is an end-to-end test framework designed to automate the testing of modern web applications. It simplifies the interaction with your app and provides a set of plugins that help you create a scalable, robust, and stable test suite. Unlike Cypress, WebDriverIO uses other languages except for javascript.

So, you can use wdio to automate:

  • modern web applications written in React, Vue, Angular, or other frontend frameworks
  • hybrid or native mobile applications running in an emulator/simulator or on a real device
  • native desktop applications
  • unit or component testing of web components in the browser

To start with webdriverIO, we need a couple of commands. 

npm init
npm install webdriverio --save-dev
npm install @wdio/cli
npm install chai --save-dev
npm install local-runner --save-devCode language: CSS (css)

Then, initialize the folder as an npm package using the npm init command. To install WebdriverIO, let’s run the npm install WebDriverIO — save-dev command. After that, we can install the CLI Runner using npm install @wdio/cli, made for running tests from the command line and installing additional reporters and services. 

Next, we should install Chai assertions. Let’s use npm install chai — save-dev for that. Finally, we need a local runner to run scripts locally. Use npm to install local-runner — save-dev in the terminal. Now we are all set to execute our WebDriverIO tests.

Basic example

describe('Test suite'), function () {
   it('search navigation on web page', () => {
       expect(browser).toHaveTitle('Outwit the Challenge')
}Code language: JavaScript (javascript)

WebdriverIO file upload

First, we will start with a file upload. There are multiple ways to do an upload in the application, and there are also numerous ways to test it. Here I want to show one simple example: a simple form with an upload button.

File upload WebdriverIO
<button class="...” type="button" data-test-type="primary" data-test="document-field-upload"> </button>
<input type="file" accept=".xlsx, .xls, .csv, .doc, .txt, .pdf, .png, .jpg, .gif, .docx" data-test="document-field-input" class="sc-pDbHj iBtvlG">
Code language: HTML, XML (xml)


const path = require('path');

await (YourPageName.addDocumentUpload).waitForExist();
await (YourPageName.addDocumentUpload).click();
await browser.execute(() => {
 const inputEl = document.querySelector('[data-test="document-field-input"]');
const filePath = path.join(__dirname, '../data/chrome.png');
await (YourPageName.addDocumentInput).waitForDisplayed();
await (YourPageName.addDocumentInput).setValue(filePath);
await (YourPageName.documentForm).click();Code language: JavaScript (javascript)

WebdriverIO will pass a script to the browser to execute, finding the input element and removing its class attribute, making the input visible. Modifying the UI for testing purposes is not a good practice. Still, we can’t get away with it any other way since the button is hidden, and the WebdriverIO can only click on it once it becomes visible. After we create a file path, we need to set the input value – the document – and submit the form.

static get addDocumentInput() {
 return $(`[data-test="document-field-input"]`);
static get documentForm() {
 return $(`[data-test="documents_smart_form_dialog"]`);
Code language: JavaScript (javascript)
File upload

Cypress upload file

From version 9+, Cypress has a built-in library to select files for input elements into the browser with the .selectFile() command. With the new .selectFile() command, you can easily select a fixture file in a form element: 

cy.get('input[type=file]').selectFile('file.json')Code language: JavaScript (javascript)

The .selectFile() command allows to dragging and dropping a file over an element, using the drag-drop action:

cy.get('input[type=file]').selectFile('file.json', {
  action: 'drag-drop'
})Code language: JavaScript (javascript)

For uploading documents, the advantage goes to the Cypress.

Assertions WebdriverIO

Assertions are the validation steps that determine whether the specified step of the automated test case succeeded or not. They validate the desired state of your elements, objects, or application under test, e.g., assertions enable you to validate scenarios such as whether an element is visible or has a particular attribute, CSS class, or state.

It is always recommended that all automated test cases have assertion steps. In the picture below, there is a screenshot from the WebDriverIO framework. We have a lot of combinations here. Also, sometimes it is not bad to have more than two expected results, depending on what we need to cover with an automation test. It all depends on the test, but globally the assertions are very similar in both frameworks.

WebdriverIO assertions

Assertions Cypress

We can broadly classify all of these assertions into two segments based on the subject on which we can invoke them:

  • Implicit Assertions
  • Explicit Assertions

When the assertion applies to the object provided by the parent chained command, it’s called an Implicit assertion. Additionally, this category of assertions generally includes commands such as “.should()” and “.and()".

  .should('have.class', 'active')
  .and('have.attr', 'href', '/login')Code language: JavaScript (javascript)

When there is a need to pass an explicit subject for the assertion, it falls under the category of Explicit assertion. This category of assertions contains the commands such as “expect()” and “assert()“, which allow you to pass an explicit subject/object.

// The the explicit subject the boolean: true
const obj = { foo: 'bar' }
expect(obj).to.deep.equal({ foo: 'bar' })
// The explicit subject here is the object obj.Code language: PHP (php)

Selecting elements in WebdriverIO and Cypress

For the elements that you need to target for both frameworks when writing end-to-end tests, it would be best to have a function that creates each element identifier uniquely so you will have some “standard”. A target element can be found in multiple ways. We can find an element by its path, content, id, etc.

Cypress discourages using existing element attributes because they have their own purposes, and tests that use them are more fragile. Instead, it suggests using a completely separate attribute. An attribute that won’t change when layout, functionality, or style changes. Examples are data-cy, data-test, and data-testid. However, stepping outside of cypress recommendations should happen on rare occasions, sometimes it’s unavoidable, like if we use third-party components.

Below is an example function that creates a unique data test:

type TestIdName = string;
type TestIdElementType =
 | 'container'
 | 'button'
 | 'input'
 | 'option'
 | 'select'
 | 'checkbox'
 | 'radio' etc…
export const buildTestId = (type: TestIdElementType, name: TestIdName) =>
 `${type}-${name.toLocaleLowerCase().split(' ').join('-')}`;
Code language: JavaScript (javascript)

After, we can create the attribute where we need it by simply using the buildTestId function within a specific component, and we will have something like this:

onClick={() => onExport(selected, 'CSV', false)}
dataTest={buildTestId('button', 'export')}
…Code language: PHP (php)

In this case the function creates an attribute, named data-test=”button-export”.

Selecting elements in Cypress

Cypress vs. WebdriverIO

What is the difference between Cypress & WebdriverIO, and which one should you pick? The following is an analysis of the comparative possibilities for both frameworks,

Cypress vs WebdriverIO framework comparison

The main reason why WebDriverIO is good is because it supports native mobile application testing, and Cypress doesn’t. Also, wdio supports iFrame, and Cypress needs to integrate an additional plugin. But the most significant advantage is that WebDriverIO supports all major browsers and multiple tabs/windows and is not limited to just one language.

QA & Dev collaboration

Developing a software/product involves a diverse set of individuals from varied departments. However, the two most important ones are the developers and the testers, who are responsible for giving life to the product. The fact that WebdriverIO and Cypress tests can be written in JavaScript, a language spoken by both groups, meant a whole lot for the entire team on the project I’m working on.

  • I, as a QA, was able to get feedback on how to use the framework in the best possible way
  • The dev team was willing to review my tests and suggest various improvements to them
  • The testing discussions became much more real cause we could use a common language
  • You can guess what that meant for the product

If we are talking about JS between developers and testers, then both frameworks are a good fit, but when that is not the case, it’s a disadvantage for Cypress, but an advantage for WebDriverIO.

Reporting in Cypress and WebdriverIO

Reporting is an inevitable factor in any test automation framework. Cypress and WebdriverIO offer reporting capabilities but differ in how they provide and display the reports. Since Cypress is bundled with Mocha, any test reports that generates for Mocha can also be utilized with Cypress. Per default, Cypress will use its specs reporter and make a video and screenshots of the test runs. WebdriverIO supports a variety of reporting methods. It has a similar specs reporter as Cypress. However, without the default capabilities or video recording and screenshots. 

Cypress vs WebdriverIO feature report


In summary, both Cypress and WebdriverIO are good choices for automated testing, and the decision between them will depend on your specific needs and preferences. Overall, if you are looking for a modern, easy-to-use solution with a rich feature set and good documentation, Cypress might be your better choice. On the other hand, if you are looking for a more flexible and customizable solution that supports a wide range of libraries and frameworks, WebdriverIO might be a better fit. Therefore, the best choice for you will depend on your specific requirements and the needs of your project.

WebdriverIO and Cypress downloads

NPM usage trends for these packages from the past five years show high adoption of Cypress in front of WebdriverIO.

Both have advantages and disadvantages, so the team as a whole must decide whether to use Cypress or WebDriverIO, but in this world we learn that only one is the winner, what do you think? Who wins?


Exceptional ideas need experienced partners.