Browser Testing With Cypress

This week I've been messing with browser testing in Cypress so I wrote some thoughts down.

Introduction

When I write code, I try to remember that everything is broken until proven otherwise. I’ve been shifting my learning to browser-based platforms that I am working on and with that shift, browser tests have started to be folded into that mindset.

Cypress is a tool for browser tests that I’ve started learning, and it’s been an interesting week. I’ve written about browser testing before, so this will be a bit less comprehensive and will mostly be my thoughts on the tool and how useful I think it is. Complete tutorials for creating end-to-end browser testing solutions using Cypress can be found in their docs.

Browser Tests

Testing has a lot of different connotations. In this context, browser tests are tests that try to use your app and tell you if something is broken. Cypress is one such tool, but there are many others.

Cypress Setup

Compared to something like Selenium, the setup was simple. Cypress advertises as an all-in-one solution for end-to-end testing. And so far, that’s been true. Selenium requires a web driver and external resources to function, whereas Cypress seems to work quickly out of the box.

Their docs suggest setting up the cypress commands in your package.json file for easier running. This is a good approach to test your app how you need to.

Example snippit of a cypress command which can be written into the local package.json file.

To help with your setup, you have access to their testing GUI.

Cypress testing GUI found on the Cypress docs website.

This is a vast improvement over other tools I’ve learned since everything can be set up in a GUI, including choosing a browser to do your testing on.

I’ve only been able to try end-to-end testing, but I’d like to dive a little more into component testing. More to come.

Simple Cypress Tests

So the tests themselves are relatively simple. The scripts only need a few lines of code, as most of the setup is in the project config and support files. Another great advantage over other tools I’ve tried so far.

A test might look something like this.

A simple test taken from Cypress docs to test if a website loads.

The above test, taken from their docs, is put into a describe() block. This gives us flexibility in creating testing classes and organizing our tests. Within that block is another block, the it() block, which is our test itself. We can be as granular as we want with our tests. For example, if we want to write an it() block for every step in an end-to-end test, we can do so with the confidence that we’ll see which stage failed.

The cy.visit() is a command and assertion. So, in this example, if a website is not sending a response, we can see this test fail. So this gives us the flexibility to write out the exact behavior we expect.

So we can add all the steps needed to test a part of our app. Like so.

Complete Cypress test example from Cypress docs

This example, also taken from their docs, takes advantage of everything described above. It also introduces chaining, which we can use for multi-step processes.

Testing GUI

OK, on to some of the stuff that makes Cypress a fun tool to dive into. Namely the GUI.

Browser-based engineering is still a space I’ve only been in for a while, so this might be new to me, but adding a browser tool for developing your apps blows me away. Let me tell you why.

So we wrote the test above. Great. Now we need directions to tell a Cypress how to navigate our app. So we need some selectors, which are always murky to me as relying on class selectors is a brittle test that can be broken with a new release. We need something better, and it’s not always clear what that “better” may be. So in comes the testing playground.

Cypress Testing Playground taken from the Cypress docs showing all the browser tools.

The above, also taken from their docs, demonstrates what made using Cypress enjoyable. Their testing suite gives you valuable tools like a real-time test runner, a test builder, a time machine so you can go through each testing step to see where issues might pop up, and an advanced selector playground.

This tool does a great job of helping you create robust selectors for your test. It allows you to hover over elements, highlight them, and the selector playground will provide you with their best guess for a cy.get() command so tests can be filled out quickly.

Some More Cool Stuff

Just a couple more things I wanted to mention. One was how easy their API makes it to creating new commands in their API for common functionality to your testing apparatus.

For example, we created one which goes to our site, types in login info, and clicks the login button. Now we have all that functionality in a single command for use in any test we need authentication for. Before long we’ll have tons of them so we can focus on testing our platform’s behavior.

Another was using what they call fixtures for injecting static data into your tests, which I love. Static data, like login credentials, names, etc, are much cleaner when you can create a JSON file and utilize the existing API to access the necessary values. I love that; it makes maintenance so much easier.

Conclusion

After all that, I can confidently say I enjoy writing tests using Cypress. It allows me to write tests the right (easy) way. Testing is often not something people think about. So make it easy to do, and Cypress does that. I’m excited to continue learning.

-George