React app testing methods to improve the performance of your development team
To keep your React apps maintainable and working as expected, testing is key. In this article we’ll cover some key strategies for testing your React application.
What is React testing?
React applications center around the concept of components, and so it makes sense to think of testing React applications in terms of components as well. Tests for a React application can be classified into three categories: (1) verifying the internal state of a component, (2) verifying the external state of a component, or (3) verifying how multiple components interact with each other.
Types of React testing
The different types of React testing include unit tests, component tests, end-to-end tests, and snapshot tests. Let’s look at these four types of tests in more detail:
A unit test verifies the behavior for a small unit of code, usually either a function or method. For React, unit tests typically verify behavior that represents part of the implementation details of a React component rather than the externally exposed behavior of a component (like a button onclick or a src attribute). If you have functionality that’s common across more than one component, you may elect to move that functionality into a separate helper function in a shared location.
Unit tests are for small bits of code, so they often will not have any React-specific behavior in them. This makes them easier not only to write (since you won’t need to rely on third-party libraries to mock React-specific behavior) but also makes them easier to read since they are typically pretty simple. Framework-agnostic libraries like Jest, Mocha, and Jasmine are typically all you’d need in order to write unit tests for your React application. Jest is a particularly good choice, as it is the library recommended in React’s own documentation, and is maintained by Facebook, the same company that maintains React. We’ve included more information about these frameworks later in the article.
Component testing tests the behavior of a component in isolation. With component tests, any state internal to the component is usually not relevant. Instead, the functionality exposed by the component is exercised by the tests (such as defining specific props). Assertions are added to verify either the external state of the component, or to verify that the appropriate modifications to shared state across components (e.g. the state of your Redux store) have been made, or both.
You can think of component tests as integration tests for your React app which verify various behaviors exposed by your component. Examples of this are testing the onclick method of an underlying div, testing a click and text entry on an input element, testing the default behavior if an optional prop is not defined, or testing how a component responds to user events (such as an onchange callback).
Several popular React libraries such as Enzyme and React Testing Library exist to make testing react components easy. Using a React-specific library is important when it comes to component testing because they will provide abstractions and helper functions that make it easier to test a component and handle behavior that’s specific to the React DOM. One particularly important aspect of component testing is the ability to render components as if the test were running in a web browser.
Testing the interaction of one or more components with each other to form entire user workflows is called end-to-end testing. This is the most complex type of testing because not only does it involve a lot of functionality, but it is also attempting to replicate how actual users interact with your application, and this is hard!
Because of this complexity of expressing user behavior in code, end-to-end tests have a reputation for being the most brittle and hard-to-maintain type of tests.
We have a lot more to say about the problems with conventional end-to-end testing tools later in this article, but before that let’s also cover a lesser-known type of testing.
A big benefit of the componentization of your application is the reusable nature of components. This can be a huge win in terms of reducing the complexity of your codebase, but one thing to be aware of is that a single change to a common component can have far-reaching effects.
Snapshot testing is a way to measure the effects of changes within your application. This is done by taking a “snapshot” of the output of your various components and comparing that snapshot in future changes to understand what resultant behavior has changed. Snapshot tests have an advantage over unit and component tests in that they can give better coverage for unforeseen bugs. However the downside with snapshot testing is that it can be noisy; specifically, you’ll get notified regardless of whether or not a change is a bug, and it’s up to you to determine if that change is expected or not.
React testing frameworks
Jest is comparable to Mocha in that it is also a test runner and test DSL, but it includes a ton of other features including snapshot testing and some React-specific niceties. It’s maintained by Facebook, which also maintains React, and is the recommended test framework within React’s own docs.
React Testing Library
React Testing Library contains a set of functions that makes it easier to test your React application, specifically around component-level testing.
Enzyme is an alternative to React Testing Library that fulfills a similar purpose; namely to make the process of creating tests for React components easier and more maintainable.
React testing FAQs
React testing can be a confusing process. Here are some of the common questions we’ve seen:
What is a React test?
React tests automatically verify behavior within your React application. The three most popular types of tests are unit tests (which verify the internal behavior of a component), component tests (which verify the external behavior of a component), and end-to-end tests (which verify how multiple components interact with each other).
What should I test in React?
When prioritizing what to test, think about what would have the biggest negative impact if it breaks, and make sure those are things you test first. Typically this would be things like common components, common helper functions, and the user workflows that are the most critical to your business.
How do I test my React JS application?
Popular libraries like Jest, Enzyme, and React Testing Library offer a great experience for creating unit and component-level tests and are easy to install (via npm install) and run (via npm test). For end-to-end testing, Reflect provides a fast and easy way to get coverage for your critical workflows without the time investment and maintenance burden of code-based end-to-end testing frameworks.
How long does a React test take?
Tests vary in duration quite dramatically. Unit tests which test small bits of code run on the order milliseconds or less, whereas end-to-end tests which are driving browser actions can sometimes take minutes to run for very complex multi-page workflows.
Why is it so hard to set up automated end-to-end testing for React apps?
Conventional end-to-end frameworks like Selenium, Cypress, and Puppeteer have a number of shortcomings that make tests hard to write and especially to maintain over time. We’ve built Reflect to make it easy to create and maintain end-to-end tests for your React app. Learn more about what we’re doing to make React end-to-end testing easy.
Start automating your React testing
Automating the React testing process can be a great way to improve the performance of your apps and prevent future bugs.
You can get started using Reflect today. Sign up for a free account and create your first test in minutes.