No-Brainer HTML, JS, CSS and cypress.io testing starter tutorial — Part 7

This tutorial series is aimed as notes for participants of workshop which will be held in OKE Software Poland. It assumes that participants have very basic understanding of HTML, CSS and JS technology. It doesn’t provide complex overview of current frontend state of the art, but rather should be treated as encouragement to further pursue the knowledge needed to become frontend dev or automated tester.

Prepartion for testing

So far we have been only interested in building our app, finally time has come to test it. Before we do that, we must prepare one thing.

The code for finished app can be downloaded from:

https://github.com/wojciech-bilicki/basic_html_js_testing/tree/finished_app

So far our app was living as a set of file on our local disk, but this is not how the web apps are really working. They’re served to a client by a server and we’d like our app to live on a server, too. Writing a server can be tricky, thankfully there are some simple servers already written for us.

We’ll install a simple server using Node Package Manager (NPM). It enables you to install and run JS libraries directly on your machine. Head to:

and install Node and NPM on your computer. What is Node? Since now we’ve been running our JS code only in browser. Node in an engine that enables you to run JS code on your machine without browser environment. In your terminal tool (I’ll be using Hyper) type:

npm -v to confirm that your npm installation finished properly. Ok let’s plug our app to npm to add our server. Go into your apps folder using terminal and type:

npm init

Now it’s time to go throught the setup process for our app. You can leave the default setting by simply pressing ENTER:

This will create file called package.json in your projects folder. It is just a simple .json file, yet it’s very powerful. You can think of it as a command center for your web app. Ok let’s actually add our server to the app we’ll go with:

Adding it to your app is as simple as writing:

npm install --dev simplehttpserver

Once this command is finished executing, you’ll see that new folder node_modules has been created inside your folder. Inside you will find another ton of folder. Why is that? We installed just one simple library! Yup, but this library has its own dependencies and also downloads them, so that it can work properly.

To start our server we need to write a simple script in our package.json file:

Now in our terminal tool we can type:

npm run start

And it will run our server! In our browsers adress bar we can type:

localhost:8000 and observe our app being loaded from our server. You can check out what is happening with the server in the terminal, where every single request for given resource is recorded. Fantastic! With that done, we can finally move to writing tests.

Writing tests using cypress.io

All code is guilty until proven else. You need to test your product and I can’t stress how important this is. Bugs will cost you money and time, which in case you’d have tests written, could be spent into new features. We all know manual testing is good and should be performed, but the true power comes with manual testing. As a tester you’ll always be working with some developers, who are producing software. There are some differences between manual and automated testing that you should now about, I encourage you to look on that article:

When it comes to automated testing Selenium was a king for a long time. It is battletested, mature and used by huge community of testers. Yet it has it many flaws:

  • It’s lacking visual feedback regarding the errors and tests themselves. While using Selenium (or one of many of it derivatives like Protactor) what you get is just some terminal statements reporting the progress and errors of your tests.
  • It’s not modern. Of course it is hardened by the years of using it all over the world, but so is jQuery and yet we decide to use stuff like React or Angular to build our apps in safer and more scalable way
  • It’s based on web drivers, which are different across the browsers, which means that if your test works on Chrome, you have no guarantee, it’ll work in Safari.
  • It doesn’t have consistent API. Cypress is asynchronous in it’s nature and has chainable commands.
  • It’s not so easy to setup on CI.
  • It doesn’t fill the gap in tester/developer/designer cooperation. The ease of writing the tests, the visual feedback on every step of running them and powerful, yet simple API, make cypress ideal tool for interdisciplinary teams.
  • Cypress has a great way to setup fixtures and stub the data and requests.

Yet, Selenium has some advantages over cypress and they are worth mentioning:

  • Selenium can be used with many languages (Java, C#, JavaScript, Python, etc.), while cypress uses only JS. I don’t see that as a flaw of cypress, since JS is the main language used to build web apps nowadays
  • Selenium has a tool for automital tests recording in Firefox (http://www.seleniumhq.org/projects/ide/), but I was never a fan of it
  • There’s this tool called Appium that is based on Selenium and can be used to do the native app testing, currently there’s no possibility to use cypress for native apps, but that would be like totally awesome.

Even so, I found that cypress is the best possible tool to test modern web apps. It’s very powerful. You should totally check the talk about it:

and of course it is more than recommended to get familiar with the documentation:

For me cypress is the testing tool, that I was searching for all these years. Let’s install it for our app and try writing some tests!

Cypress Tests

Our tests will be based on gherkin test cases which can be found in:

https://github.com/wojciech-bilicki/basic_html_js_testing/tree/features_added
in features folder.

Cypress can be added to the project via npm or can be downloaded as a standalone app. You are free to choose your preferred option, but I’m gonna go with npm.

Using the terminal go into your apps folder and type:

npm install cypress --save-dev

Than go to your package.json and add change test script to:

"test": "cypress open"

This will run cypress and setup some example specs for you. They can be found in cypress/integration/example_spec.js and describe many of cypress features, while testing example app. We’ll get rid of them and write our own. In cypress/integration folder create home_spec.js file. Cypress is using BDD syntax based on describing the behaviour of given parts of your app. We use describe command to initiate the section and it to describe a single feature. Together it reads like a natural language:

Now if we run npm run test in our terminal, we’ll see the cypress app:

From here we can go to docs, run our tests, change our settings and many more. If we click on our test file, we will actually trigger the test run:

This is the testing tool that I was looking for. It has instant visual feedback loop. It looks clean and is easy to read. We can see that our page actually loads. Let’s go ahead and disable our server for a second and see what happens:

We can see that cypress is reporting that the page cannot be loaded. Let’s bring our server back to speed and focus on testing itself. I’d really like to dive deep into the cypress powerful functionalities, but we’ll only scratch the surface as the app itself is rather simple, but I really encourage you to use it in your projects and see what it can actually do.

Let’s go to our concert_table.feature file and try to test our first requirement.

Feature: Concert table 
As a user I want to see all concerts in table so I could decide which concert is interesting for me
Scenario: Concert table view  
Given I am on 'Main' page
When I observe 'Table' section
Then I see header elements are displayed correctly
And I see row elements are displayed correctly
#Expected behaviour:
# * header displayed correctly should contain titles of columns: ARTIST, CITY, DATE, PRICE, TICKETS
# * header elements should be capitalized
# * row displayed correctly should contain:
# - picture and name of artist in first column,
# - city and shortcut for state in cloumn city,
# - date in format YYYY-MM-DD
# - price and currency
# - amount of tickets selected by user to buy - buy default set as 1
# - green circle with + symbol (add symbol)

Ok so let’s try to test whether the concert table headers are correctly displayed. In cypress/integration let’s create home_spec.js file and write:

So this is our first cypress test. We use css selectors to find the element that interests us. This time it is first header of our table and we’d like it contain text ‘Artist’.

Nice, but what if we’d like to work with whole array of our headers? Maybe we could just assign our headers to a variable, like this:

NOPE. You see Cypress calls for elements are asynchronous and we must wait for the call to resolve to get what we asked for. We use .then function to get element that we are searching, like this:

Let’s actually fulfill first test case, starting with headers having correct names:

Now let’s confirm that the rows (at least one) is being displayed and it has correct elements inside of it.

Some code needs to run before each and single test for example before every one of our tests we’d like to visit our website. Therefore we can use beforeEach hook to move code that repeats itself out of our testing functions. Next we test our table row to check whether it contains image and name span.

Then we can check for the correct format of the city as well as format of the date. We should also check the input and button for being correct:

There are many interesting thing we do here. We can check for the format of the date and city using regular expressions. You can see that cypress is based heavily on chaining commands together. This is somehow different from Selenium is offering. I find it more readable. Two things to remember here:

  • get command is always executed against whole page so the whole document will be queried , but we can narrow its scope using within function. So get and within together can work as find.
  • value of the input is returned as string we cast it to Number to match it against expected value

I encourage you to read through the docs of cypress, follow them on facebook and go through their examples page. In our next chapter we’ll dive deeper into cypress and testing our app. Cheers!