by Francesco Agnoletto

The importance of testing

Examples of how to increase your app reliability

Photo by Markus Spiske on Unsplash

Testing is a part of front-end development that I often see forgotten, yet it can play a major role in the reliability of a project.

What a good testing suite can provide

Having a good testing suite raises the confidence in the code you deploy. Knowing your app works as it is supposed to do removes a lot of hidden issues and doubts.
Detecting bugs with tests before you deploy is far better than having your users deal with them.

QAing everything by yourself can take a lot of time and the result would still be sub-par. A good testing suite automates most of this process, freeing you more time in the long run.

Challenges in testing a front-end application

Front-end adds a layer of complexity for your application: the user. Tests should take into account users by being able to cover what the user does, not only code.

The current JavaScript ecosystem keeps evolving at a very fast pace. Tests that rely on the internals of the libraries make for brittle tests, prone to break as the APIs change.

Most modern applications use a global state to connect different parts of the code. Most components will want access to this global state, so we have to account for it in our tests.

A Philosophical approach to testing

End users don’t care how you handle your global state, they care that when they try to log in, it works. When users click buttons around they expect them to work. That’s what we should test, what the user sees and does.

Since dependencies can change, our testing should be as library-agnostic as possible.

Testing is about making your life simpler, not harder. Don’t write tests for the sake of writing tests, if there is no value in a test, don’t write it.

The libraries used in the following examples are jest, react and react-testing-library. The end-to-end test using casperjs as browser testing utility.

Types of tests

There are a few different types of tests, we can adopt to solve the problems outlined above.

Unit tests

unit-test

A simple unit test for testing the input and output of a function. In the example, the function accepts a string, if it is a URL, returns the domain name and top-level domain. In case http or https is not present, returns the input.

The test for this function sends the 2 possible inputs and checks if the outputs match what we expect.

Snapshot tests

snapshot-test

Using a test renderer we can simulate a component and save a snapshot of the rendered element.

snapshot

The test will then compare the new snapshot to the previous one for inconsistencies.

These tests can simplify testing UI, but they will break as the UI changes. If your application changes too much, other unit tests will provide more stability.

Integrated unit test

integrated-unit-test

A test render can do for more than snapshots. By firing simulated events we can check our components behavior.

In this example, we create a table holding two values 2 and 1. We then simulate sorting the table and check the first value.

End-to-end test

end-to-end-test

These can be harder to set up. The example uses casperjs as I found it to be easier (also it’s free) than the alternatives.

This kind of tests mock an entire browser to execute the commands provided in the test.
In this example we take a screenshot of the login page, fill the form and take a new screenshot once logged in.

End-to-end tests can help strengthen your testing suite. A good codebase should include both unit tests and end-to-end tests.


Closing tips

There are more ways that can increase the quality of your application and your tests.

Css-in-js solutions like emotion allow you to snapshot the style generated by your components. This increases the coverage your snapshots can provide.

Using a CI solution like travis-ci or circleci is the standard for unit tests. You can also schedule end-to-end tests to run daily as a health-check for your application.

Even after such a complete testing solution, bugs can and will still appear.
Error tracking software like sentry or bugsnag can help you identify problems faster.

Testing an important part of programming. It reduces bugs, increases reliability and confidence in your code. Part of being a good developer is to know how to write effective tests.

Adapted from my presentation on the new front-end testing suite for streamroot.