End-to-end testing is an important aspect of software development. Many companies use testing to make sure their products are having the right quality. One of the tools that can be used for end-to-end testing is Cypress.
What is Cypress?
Cypress is a JavaScript based testing framework built on top of Mocha (another JavaScript testing framework). Compared to other testing tools, such as Selenium, Cypress doesn't use a webdriver to run the test. Cypress is executed in the same run loop as your application. It uses a Node.js server process to communicate with the testing.
In addition, there are several advantages using Cypress:
- Automatic waiting - Cypress automatically waits for the DOM to load the elements to become visible. You do not need implicit and explicit waits to wait for elements before it is loaded.
- Real-time reloads - Cypress automatically saves your test file after it has been adjusted and reload the newly made version automatically. No need to do it manually.
What you might need to know before continuing with this tutorial
While I am going to try to make this tutorial beginners-friendly, there are some things that might be useful to know before continuting with this tutorial:
- HTML & CSS
- JavaScript concepts such as arrow functions, asynchronous and promises
- Preferable, but not needed: Mocha
Installing Cypress
Before we can install Cypress, you have to make sure you have node.js
& npm
installed on your computer. If you haven't installed these yet, go to the official Node website and download the latest Long Term Support (LTS) version.
To verify you have installed Node.js and npm, open the terminal or command prompt and type the following commands:
For NPM:
npm --v
For Node:
node -v
If you get a version number back as a response, it means you have installed them successfully on your device.
Now we can finally install Cypress. To install Cypress we need to run two commands:
-
npm init
- this command creates apackage.json
with all the dependencies that are available within the project -
npm install cypress --save-dev
- this command installs Cypress locally in a project folder. This process can take a few minutes to complete.
To launch Cypress we can run the command ./node_modules/.bin/cypress open
in the terminal. This will open Cypress and this new window below. All these files are example tests that you get when you install Cypress for the first time. They are located in the 'integrations' folder.
Open your text editor and go to the Cypress project folder you've just created. You are free to use whatever IDE you prefer. I am going to use Visual Studio Code.
If we run one of the tests in the Cypress window, we will see page like this:
On the left we have the name of our group of tests and the names of our individual tests below. On the right we see the output of our tests displayed in the browser. We can go back and forth to see what are the results of our tests are.
Creating a Cypress test file
Let's create a test file in Cypress. First, delete the 'example
' folder in integrations
with all the test files.
Creating a Cypress test file
For the test we are going to use this demo website.
For the syntax of a test file we can use the code below. Let's break them down.
/// <reference types="cypress" />
describe("Account creation", () => {
before(() => {
cy.log('Tests have been started')
})
beforeEach(() => {
cy.visit('https://www.demoblaze.com/index.html')
// Click on the sign up button
cy.get('#signin2').click()
// Verify sign up page
cy.get('#signInModalLabel').contains('Sign up')
cy.wait(2000)
// Function that generate a new username with each new test
function generateNewUsername() {
let text = "";
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
for(let i = 0; i < 10; i++)
text += alphabet.charAt(Math.floor(Math.random() * alphabet.length))
return text;
}
const generatedUsername = generateNewUsername()
// Write the username and the password
cy.get('#sign-username').type(generatedUsername)
cy.get('#sign-password').type('randompassword')
})
it('should create a new account for the ecommerce website', () => {
// Click on the Sign up button
cy.get('button').contains('Sign up').click()
// Verify alert message
cy.on('window:alert', (str) => {
expect(str).to.equal('Sign up successful.')
})
})
it('should cancel creating the new account for the ecommerce website', () => {
// Click on the close button
cy.get('#signInModal > .modal-dialog > .modal-content > .modal-footer > .btn-secondary').click()
// Verify the sign up page is not visible
cy.get('#signInModalLabel').should('not.be.visible')
})
afterEach(() => {
cy.log('Test has succeeded.')
})
})
References
At the top of your file you need to put /// <reference types="cypress" />
. This is to make sure that we can use the Cypress syntax.
Describe()
Then we see the describe()
method. The describe
method indicates what the name of our group of test is. It takes two arguments: the name of the test case in strings and an arrow function.
Hooks
In the test file, you can see before(),
beforeEach()
and after()
. These are called hooks. Hooks are used to setting up preconditions in your testing and also to clean up your test. By using hooks the code is much cleaner and we can prevent code duplication. In Cypress there four types of hooks:
-
before()
- run once before all tests indescribe()
-
beforeEach()
- run before each test indescribe()
-
after()
- run once after all test indescribe()
-
afterEach()
- run after each test indescribe()
it()
The it()
method is a method that describes the name of the individual test. Like the describe()
method, it takes two arguments: the name of the individual test and an arrow function.
In-built methods in Cypress
There are many methods available in Cypress. There are too many discuss so I will discuss some of them that are common. If you want to know more Cypress methods, check out the documentation.
In Cypress we write code like this:
cy.log
-
cy
- the first thing you have to write to declare you're using a Cypress method -
log()
- example of the built-in a method that can be used
Command chaining
What we also can do is use multiple Cypress methods and combine them together. This is called command chaining. An example of a command chain looks like this:
cy.get('#sign-username').type(generatedUsername)
Let's break the code down:
-
cy
- declare you are using a Cypress method -
get()
- method to get an element -
type()
- enter text in the retrieved element.
Assertions
Last thing we can also do in Cypress is to assert. Asserting in Cypress is to verify that a certain element or other value is available in the webpage. An example of an assertion looks like this:
cy.get('#signInModalLabel').should('not.be.visible')
We retrieve the element using the CSS selectors and use the should method to verify that the element is not visible. There are other types of assertions available that you can find in the documentation.
Wrap up
I hope this tutorial taught you how to use Cypress and the basics are understandable. If you enjoy this article, share it with your friends/followers. If you want to read more articles, make sure to join the newsletter.
If you want to watch a video, I made a playlist on how to use Cypress. Check it out below 👇
For more articles check out https://helloiamarra.com/ for more tutorials.
Top comments (5)
What about testing on Safari and Internet Explorer?
At the moment Cypress doesn't support Safari and IE. It supports Chromium based browser and Firefox.
That's a shame.
Not testing on all major browsers is almost like discriminating users who do not want to use Chromium based browsers or Firefox.
I actually just watched a tutorial on testing earlier today and for e2e testing they used Puppeteer. How does Cypress compare and contrast to Puppeteer?
They are similar, but Puppeteer has some advantages.
With Cypress, you cannot test on multiple browser tabs, which makes it difficult to test a lot of scenarios, like signing in with a 3rd party service or even something as simple as clicking the Social Media links from the footer of your website and checking if they can be clicked and that they take you to the right destination.
But you can do that with Puppeteer.
Another advantage of Puppeteer is that it's completely open source and free, without any limitations.
Cypress is a free npm package, but there is a paid component called Cypress Dashboard service, which is not free and you might need it in a lot of real-world scenarios.
You should also consider Playwright.
I wrote a detailed comparison here.
But that comparison is based on our own specific needs.
For example, maybe you are testing an internal app and you won't need to do cross-browser testing in Safari and Internet Explorer and mobile devices.