Cypress insider: How to set your Testing Environment and run your First Test

A brief overview of why Cypress is a great choice for testing, including installation, project setup, and optimal testing.

  • cypress

Why choose Cypress

Testing capabilities

Cypress has a friendly user interface that provides simple, human-friendly syntax, which makes it great for both beginners and experts. You can simulate user interactions like clicking buttons and filling out forms, making it perfect for testing your web applications thoroughly.

Consistent cross-browser testing

Another of Cypress' benefits is that it supports multiple browsers, ensuring your application works well for all your users, regardless of which browser they prefer. In testing, this is helpful to identify and fix browser-specific issues early on in the development process.

Community and documentation

Cypress has a relatively big community and excellent documentation. The community actively contributes, meaning you can find answers to your questions and difficulties. At the same time, there are also plenty of tips and even pre-written code snippets that are easily findable. Additionally, many people and channels contribute to the community by posting tutorials about practically everything you search for. There is also a well-maintained documentation website that provides clear explanations for every code snippet and good general guidance, making it easy to begin using Cypress and stay aware of the situation.

Setting up your testing environment

Installation and setup

The first step in setting up your testing environment with Cypress is installing it on your device. Before attempting that, make sure to check your device is compliant with the requirements from the documentation. After that, you can start making a designated folder and name it correctly, as this will be your project folder. Afterward, open the code editor you prefer (I recommend VS Code, so let's use it for reference) and open the folder in the editor. The next step is to open your terminal in VS Code and to install Cypress in the project folder itself with the npm install Cypress --save-dev command, after which, as soon as the installation finishes, you will have several files generated on the left side. By default, your tests will be written in the spec.cy.js file, but you can always change that and set it per your preferences. So far, this is all you need, and you can begin putting the configurations for your project.

provided with freely accessible code from the article in a public Github repo for your convenience

Project configuration

In this step, you need to set the best testing environment specifications for your project, which you can do from here. That means setting a specific browser to test with particular parameters like height and width, and you can also set a base URL to be tested, which means that you can avoid it as a step in your tests. Of course, some of these steps are non-obligatory, so excluding the ones you cannot test without, it is entirely up to you to set whatever pre-conditions you prefer. Remember that the available documentation will also give you plenty of other recommendations. You should check it out here to get some ideas.

Integrating with your application

By this, I mean that before testing whatever website you're about to test, ensure it's accessible on the web and exceptionally reachable by Cypress. If it has any access limitations or restrictions, this would potentially interrupt the testing process or prevent it from starting. Writing your first test

Creating test files

So, you set your project specifications, and now you must decide where to write your tests. Naturally, the first step is creating a test file, usually in the e2e folder. Also, if your test file has a longer name - you can connect it with dashes - for example, 'edit-my-profile-page.cy.js.' __Always remember that the extension for your testing suite files is not just .js it's .cy.js.

Clear and precise name given to test files becomes a crucial part of keeping project cleanliness in time, and proper naming pays off as the number of tests increases. This is particularly evident for above, let's say, 100 tests.

Writing the tests

Here is the step where the essence of our job takes place: we begin writing tests. We will proceed here by considering that we already have test specifications prepared and reported test cases; now, we must transform the written scenarios into difficulties.

Here is a simple overview of how it looks:

describe('Most basic Google tests', () => { it('Successfully opens Google url', () => { cy.visit('https://www.google.com') cy.url().should(‘eq’, ‘https://www.google.com’) }) })

You begin by using describe() to define your whole test suite. It's good to clarify that the test suite contains as many tests as you want. Still, it's strongly recommended that all of them are related to one application module and that they are located in different folders - for example, the folder Authentication should only contain the file authentication.cy.js, the folder Navigation bar should only contain navigation-bar.cy.js and likewise for home page, etc. If you're working on a more extensive website that can potentially have login options from a third party like Facebook or Google - you can have several files in the authentication.cy.js - one file for login with credentials, let's call it standard-login.cy.js, Google login file called google-login.cy.js and a Facebook login file called facebook-login.cy.js, etc. Let's analyze the test, which is supposed to check that the Google URL opens successfully.

describe(Most basic Google tests, () => { ... })

We give our suit a proper name (which often overlaps with the test file name)

it('Successfully opens google.com', () => { ... })

Here is where we give our test a proper name specifically related to what it should do. This means that if the idea is for the test to visit a website successfully, then we should specify the "successful" part especially. That way, we can differentiate between positive and negative test scenarios еasier and not mess up with test names. After all, every test is supposed to test something different from all others, so the uniqueness in the name is a must.

cy.visit('https://www.google.com')

The cy.visit() command instructs Cypress to visit a specific URL. This step cannot be skipped in any way, whatever you test, because Cypress is designed to test websites. Before writing your first command, it is an excellent reminder to refer to the documentation. Constant checks will save time, prevent code inconsistencies, and boost effectiveness.

cy.url().should('eq', 'https://www.google.com')

In all honesty, this is the last but crucial part of the test, which a beginner QA is likely to forget once or twice. The assertion part is where we instruct our Cypress to compare the URLs it visited specifically and to check if they are the same. If they are not, Cypress didn't successfully visit the URL we told it to visit, or we were redirected, and the assertion will fail. And so will the whole test, respectively.

Running and debugging

After writing our test, we can return to the terminal and note that the npx cypress is open to run Cypress. After that, click E2E Testing from the window:

cypress-1

After you do that, this window will open:

cypress-2

Click Start E2E testing on the browser we choose; I recommend Chrome. That will open a new window containing the specs page. From here, you should select Create new spec:

cypress-3

And then you will see this:

cypress-4

Directly click on Create spec and here:

cypress-5

Okay, run the spec. This will generate your first test from Cypress, and you can observe how the program runs the tests.

The test will pass because everything assigned by default is correctly written. However, when we write a test, and it fails, Cypress offers a little bit of info to identify and fix the problem, such as what exactly did not happen as expected and on which line of code in your file. So you can inspect the application's state and understand why a test didn't behave as expected.

You can now go back to your code editor at spec.cy.js, the file that contains one automatically generated test, which is situated in the e2e folder in Cypress (cypress/e2e/spec.cy.js).

From here on, we can edit our file name according to our test coverage and edit the test correctly, like, for example, changing the name of the test suite, the name of the test itself, and also the website in the trial from example.cypress.io to www.google.com, the commands, etc., so that we can simply perform our first exploratory testing and see how Cypress works.

Cypress best practices

Pinpoint the objects you interact with

Make the best possible use of the page elements (header, footer, login modal, search results field, etc.) when building your selectors. It will help you make a logically correct test that's easy to read and maintain. Let's say you're writing a test where you have to open a login modal via a button in the site's header. The right approach, in this case, is to incorporate the footer in the selector. Its ID can do this, or if it doesn't have one - by its tag name and class. Chances are that you won't be the single QA in your company. Someone will look at your test and read: you open this site, in this site, you go to the footer, and within the footer, you click on a button that opens a login modal - plain and simple. It is understandable to read.

I would also suggest that if you have no prior knowledge - you go through a crash course in HTML and CSS; it will expand your general idea of how they are built because we QAs interact with them all the time.

Write compact tests

Think of test writing as if you're packing a suitcase - you want to include only the essentials, not have the whole house stuff. A proper test doesn't need to include steps that don't particularly add any use. You don't need to instruct Cypress to open a modal that doesn't need to be opened, just like you won't take knives and forks when you go to a restaurant. A compact test means no unnecessary code writing, saving time as unnecessary steps will not be executed. It's also a good idea to have your code prettier because it's natural to become messy when writing tests. A prettifier comes in handy to tidy up the code once you finish writing. Here's the one I use for Visual Studio Code.

Write versatile tests

Writing versatile tests, from my perspective, means several things - in this case, we're talking about Cypress, which is JS-based. Therefore, almost all functions and capabilities of JS can be applied to test writing (such as loops, functions, variables, etc.) despite Cypress itself having its syntax. As for how to maximize the effectiveness of the tool to the best degree - we can make use of custom commands, for example. Suppose you have ten tests containing identical first two or three steps. You can combine the respective steps in one test. For example:

Cypress.Commands.add('login', () => { cy.get('#username-input-field').type('My username') cy.get('#password-input-field').type('My password') cy.get('#login-button').click() })

Afterward, this command, which we named 'login,' we can apply like this:

describe('Authentication', () => { it('Successful login into the system', () => { cy.visit('https://www.mywebsite.com') cy.login() cy.url().should(‘contain’,/profile’) }) })

This saves us the effort of writing the same steps for many tests and keeps tests cleaner, and when you make changes to the code, you just change only one place. All commands should be stored in the commands.js file, after which you can import them into the test file with

import '../../support/commands'

Also, include constants in your tests to avoid magic numbers. If they're to be used in one test suite only, you can write them in the test files you're working with. Here is an example of how a constant can look if it's stored and used in one test file:

const inputField = '#input-field’

However, if your const is to be used in three different test suites (which means three different files, respectively) - then you should consider creating a separate file called constants.js and store them there with the export keyword:

export const PASSWORD_INPUT_FIELD = '#password-input-field’'

After that, to apply it in your desired test suite file, you should import it at the beginning of the file this way:

import { PASSWORD_INPUT_FIELD } from '../../support/constants'

Conclusion

For anyone considering a testing tool for their automation journey, I can confidently say that Cypress is an excellent choice. I've enjoyed using Cypress for over a year, and I can attest to its remarkable user-friendliness and various capabilities. If you're about to embark on your automation testing adventure, I strongly encourage you to try Cypress!

Q&A

Build your digital solutions with expert help

Share your challenge with our team, who will work with you to deliver a revolutionary digital product.

Lexis Solutions is a software agency in Sofia, Bulgaria. We are a team of young professionals improving the digital world, one project at a time.

Contact

  • Deyan Denchev
  • CEO & Co-Founder
© 2024 Lexis Solutions. All rights reserved.