The importance of building a good testing suite for front-end development projects
By: Francesco Agnoletto
Tags: Web Development, CSS, React, End To End Testing, Testing

The importance of building a good testing suite for front-end development projects

Examples of how to increase your app reliability

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. In developing Streamroot’s brand new customer-facing dashboard (which you can read about here and see here), we put in place a full testing suite to ensure the proper functioning of all components: data visualizations, buttons, reports, billing and account information, and more.

Here I offer a few examples of unit tests and end-to-end tests that can help front-end developers working on this type of project to increase the reliability of their code while saving time on QA.

What a good testing suite can provide

Having a good testing suite raises the confidence in the code you deploy. Knowing that your app works as it is supposed to remove 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 results are still 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 is 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 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 uses casperjs as a browser testing utility.

Types of tests

There are a few different types of tests that 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, it 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 two 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 output

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

This test 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 tests

integrated unit test

A test renderer can do far 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

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

This kind of test mocks an entire browser to execute the commands provided in the test. In this example, we take a screenshot of the login page, fill in 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 can increase 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 building such a complete testing solution, however, bugs can and will still appear. Error tracking software like sentry or bugsnag can help you identify problems faster.

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

If you are intrigued by what Streamroot does and interested in working on this type of customer dashboard, check out our open positions or drop us a line at jobs@streamroot.io!