fbpx

Recently, I was trying to improve the quality of the software we ship and I came across this tool called Cypress! Cypress is awesome and you can build end to end (e2e) UI testing solutions with it. In this post, I will talk about,

  1. the first time I built an e2e testing solution
  2. what Cypress is, and
  3. provide a walk through of how to build a solution with Cypress.

Background

I am a full stack engineer and not a QA engineer but I often find myself working in small engineering teams where there are no QA engineers. Hence as a full stack engineer it’s up to to me to establish a framework for and write some e2e UI tests.

I remember building an end to end (e2e) UI testing solution at my old workplace in 2015. My goal was to cut down some of the time I would spend on testing. I was working on a AngularJS (i.e. Angular 1.0) application at the time and I built the e2e testing solution using Protractor. I managed to build a fully working solution but it was not easy… not at all! It took quite a bit of effort including spending a weekend of my own time just to get things going. You can read about that here

https://mydaytodo.com/protractor-e2etests-angular/

That was 2015 and with Protractor, in comes 2020, I come across Cypress and things are a little different. Different how? I will get to it but first let’s learn a little about what Cypress is.

Cypress

It does not use Selenium!!! That’s one of it’s most standout features to me. Most testing frameworks prior to Cypress were built with Selenium e.g. Protractor (mentioned above), Webdriver etc. Then they bundled some sort of assertion library e.g. Chai.js. Cypress is an all inclusive one-stop solution for all your testing requirements. Also, it supports some JQuery style selectors and overall is quite easy to get started with. As someone who’s worked on setting up an e2e testing solution using a Selenium based framework, I appreciate how easy things are with Cypress.

Cypress only focuses on front-end testing where you can write all your tests in Javascript. I think that’s a good brief introduction to Cypress and now let’s see Cypress in action by writing a test

Testing a web page

In this section, we will look at building a web page of a large application.

Scenario

Let’s say we are part of an organisation that has built a large website with a number of disparate elements to it. Now, one of the things we have struggled with in the past is that, every time we add a new page to the site, before it’s live, we can’t always ensure

  1. That the design layout for mobile and desktop conforms to original designs
  2. The font-size is the same as the company font
  3. The headers do not conform to the standard company header font

We will try to address the above concerns using Cypress. Not sure if I could have defined a problem to be anymore front-end than this 🙂 Cypress is capable of doing a lot more but in the interest of not making this post too lengthy, we will just do some front-end tests here.

Let’s start by looking at the code for our html page that we will test.

HTML Web page

Here’s the HTML code that will be tested. This time, we will be writing simple front-end tests

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="index.css">
    </head>
    <body>
        <div class="parent">
            <div class="box lightgreen">
                <span class="companyFont mainHeader">Hello there</span>
            </div>
            <div class="box red">
                <span class="companyFont notMainHeader">Hello there</span>
            </div>
            <div class="box violet">
                <span class="companyFont notMainHeader">Hello there</span>
            </div>
            <div class="box thistle">
                <span class="companyFont notMainHeader">Hello there</span>
            </div>
        </div>
    </body>
</html>

The above code is just a simple html page with

  • A few divs with
  • headers where
  • one of the divs has text which is a title and it
  • has some text that’s just normalText. The rest,
  • of the divs have text of type subHeader and all,
  • text on page should be of type companyFont. Lastly,
  • the page uses flex layout where,
  • on desktop, divs are arranged in rows and on mobile as columns

The css to style it all is here,

.parent {
    display: flex;
    flex-direction: row;
}
.box {
    width: 300px;
    height: 300px;
    margin: 10px;
    border-radius: 10px;
    padding: 5px;
}
.companyFont {
    font-family: Verdana sans-serif;
}
.title {
    font-size: 32px;
    font-weight: bolder;
    color: white;
    text-decoration: underline;
    text-decoration-style: wavy;
}
.subHeader {
    font-size: 18px;
    font-weight: bolder;
    color: white;
}
.normalText {
    font-size: 16px;
    padding: 8px;
    text-align: justify;
}
.lightgreen {
    background-color: lightgreen;
    box-shadow: 5px 5px 5px lightgreen;
}
.red {
    background-color: red;
    box-shadow: 5px 5px 5px red;
}
.violet {
    background-color: violet;
    box-shadow: 5px 5px 5px violet;
}
.thistle {
    background-color: thistle;
    box-shadow: 5px 5px 5px thistle;
}
@media only screen and (max-width: 690px) {
    .parent {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .violet {
        display: none;
    }
}

We probably don’t need that much css but you know just in case…

I realise this is a bit simple and you may, think is this even necessary? Maybe not! However the goal of this post is to get some familiarity with e2e testing with Cypress, before moving on to tests with UI interactions. Now, the first thing we need to do is,

Setup Cypress

On Ubuntu and MacOS at least, this is not that hard (not sure about Windows). Simply,

  1. navigate to the project directory cd projectName
  2. and execute npm install –save-dev cypress
  3. open the Cypress test runner by npx cypress open or node_modules/cypress/bin/cypress open while still in your directory

When the cypress runner (headless chrome)  launches, you will only see some (very useful) test examples provided by Cypress. This is because we have not written any tests yet and that’s what we will do next.

Like the blog? Subscribe for updates

Before we write our first test

For us to be able to run our test, the Cypress test runner should be able to access our index.html page. We could do it locally but let’s serve our index.html file with nodejs. I am not going to get into details of this, but we will create a simple server and here’s the server.js code

var connect = require('connect');
var serveStatic = require('serve-static');
/* __dirname same as path.dirname() */
connect()
    .use(serveStatic(__dirname))
    .listen(8080, () => console.log(`server running on 8080`));

As you can see, it’s a very basic server that can serve our html file via http://localhost:8080/index.html

p.s. for me the one true default server port will always be 8080, long live Tomcat!!! 🙂 

A Cypress front-end test

Let’s write some tests to cater for things mentioned in the above scenario. Aspects of the front-end that the organisation has struggled with in the past. Hence we will write tests to determine,

  1. If the company header is the right font-size
  2. The font is consistent with the company font
  3. The header is correct

Here’s the code for a few simple front-end tests with Cypress.

describe("Front-end UI tests to ensure consistency", () => {
    /* visit this page before running any test */
    beforeEach(() => {
        cy.visit(`http://localhost:8080/index.html`);
    });

    it("Should test if header is 32px and wavy", () => {
        return cy.get(".title")
        .should('have.css', 'font-size', '32px')
        .should('have.css', 'text-decoration-style', 'wavy');
    });
    it("Should test if data is shows as rows on desktop", () => {
        cy.viewport('macbook-15')
        .wait(200)
        .get(".parent")
        .should("have.css", 'flex-direction', 'row')
        .should("not.have.css", 'align-items', 'center')
    });
    it("Should test if data is shows as columns on mobile", () => {
        cy.viewport('iphone-6')
        .wait(200)
        .get(".parent")
        .should('have.css', 'flex-direction', 'column')
        .should('have.css', 'align-items', 'center')
    });
    it("Should test violet has no box shadow on mobile", () => {
        return cy.get(".violet")
        .viewport("iphone-x") 
        .should("not.be.visible");
    });
    it("Should check if we have the right font type", () => {
        return cy.get(".companyFont")
        .should("have.css", "font-family", `"Verdana sans-serif"`);
    });
});

All the test code pretty much speaks for itself. The above tests make use of what we call BDD assertions. BDD i.e. behaviour driven development. Have a look at the code where we are changing the viewport. What I love the most about Cypress is the ease of testing your UI on different screen sizes.

Error you may see…

Early on when I was preparing the code for these tests, I encountered a problem. The issue was the Cypress test runner was resizing the window to a smaller screen but the CSS media query wasn’t being applied. Hence the test for the flex-direction to change to column on mobile was failing. I simply couldn’t understand why? When I was changed to a mobile screen it while running my tests on Chrome browser, it applied the CSS breakpoint and changed the flex-direction. After doing some research, I came across the issue on the Cypress Github repo

https://github.com/cypress-io/cypress/issues/970

Anyway the solution is to use max-width as opposed to max-device-width in the CSS media query.

Summary

I realise these tests seem trivial but think about it, if you setup a standard by which all new web pages added to a site has to pass a test, don’t you think it will help? One example could be, for the new developers joining your team. They will not know about the standard company fonts, headings or the company style in general. Hence, having mandatory tests such as these that their new web pages needs to pass, makes their initial onboarding process easier. You can find all the source code for this post on this Github repository.

Anyway, in this post, we explored a scenario of validating styles in our new html page by writing some e2e tests with Cypress. I hope I can find the time to write another post that cover writing tests that involve some UI interaction.

Like the blog? Subscribe for updates

As usual, if you find any of my posts useful support us by  buying or even trying one of our products and leave us a review on the app store.

‎My Day To-Do - Smart Task List
‎My Day To-Do - Smart Task List
‎AUD $ Currency Converter
‎AUD $ Currency Converter
Developer: Bhuman Soni
Price: $0.99
‎My Day To-Do Lite - Task list
‎My Day To-Do Lite - Task list
‎Snap! I was there
‎Snap! I was there
Developer: Bhuman Soni
Price: Free
Numbers Game: Calculation Master
Numbers Game: Calculation Master
‎Simple 'N' Easy: Todos & food
‎Simple 'N' Easy: Todos & food
‎Captain's Personal Log
‎Captain's Personal Log
Developer: Bhuman Soni
Price: $4.99
My Simple Notes
My Simple Notes
Developer: Bhuman Soni
Price: Free
‎My Simple Notes - Dictate
‎My Simple Notes - Dictate
Developer: Bhuman Soni
Price: $2.99

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *