Introduction to React Testing Library

Adarsh Pandya
Simform Engineering
7 min readSep 18, 2023

A beginner’s guide to React Testing Library.

“All software you write will be tested — if not by you and your team, then by the eventual users — so you might as well plan on testing it thoroughly.”

~ Andrew Hunt (The Pragmatic Programmer)

You might have come across situations where you found a developer saying, “But that worked on my machine!” or “At the time of development, it was working as expected.” Let’s be honest; it’s tough to identify what caused the failure when dealing with a huge code base.

Software, unlike humans, needs to be responsive 24x7, and the only way to make sure that software is behaving as expected is to write maintainable code with proper test coverage for various scenarios in different environments.

The Problem

A broken website with a blank page on error vs a functional website with a proper error message.

Let’s consider a real-world scenario: You’re a front-end engineer working on a new social media application. The task at hand involves displaying posts in a news feed for our users. Here’s what your process looks like:

First, you set up a meeting with the back-end developer to discuss the API contract. Your expectation is to receive a collection of posts in response to a query call.

As a React developer, your responsibility is to fetch these posts from the back end and map them one by one in your news feed component. However, this seemingly straightforward task comes with its fair share of potential pitfalls. Let’s look at them one by one 👇

  1. The request may return a single object instead of an array of posts when you only have one post stored in the back end.
  2. A post from the collection of post may be missing some required field that is necessary for content to be rendered on screen.
  3. There are chances of getting an error in response when the server goes down.

As front-end engineers, we always try to cover such edge cases while designing the component. However, due to various reasons, there are times when we overlook these scenarios. The reality is that sometimes the component implementations are fragile in nature, which may result in a live website crashing with an empty screen when our end users encounter issues. Wouldn’t it be great if we covered all those edge cases? Wouldn’t it be great if we had pre-planned such scenarios and showed some custom messages to our end users rather than them figuring out what went wrong?

Why is testing necessary?

Scaling modern-day websites with ease

Have you ever heard of the term “Returns on investment?” I think there should be a term similar to that for the software industry. “Returns on software” refers to a satisfaction level calculated based on how reliable your software (or website, in this case) is and the ability of your software to tackle various unexpected scenarios. Covering such edge cases reflects your empathy toward the end user. The reliability level of your software is directly proportional to the coverage of unexpected edge cases. Testing makes the software more fault-tolerant. Additionally, it gives developers the confidence to make changes in the code base without any fear, resulting in a faster development cycle.

The Solution

Now that we know the underlying problem, we all wonder, “Is it possible to cover such edge cases just by relying on the gut instincts of the developer? Is it reliable to depend on our guts, especially when working on such kind of fragile functionality?” Well, the answer is no. As a developer, we tend to think more towards the complexity of the functionality implementation, not that we don’t think of edge cases, but we miss covering all of them sometimes. To be very honest, it’s tedious and time-consuming to check each and every edge case as and when we change something in the application.

Wouldn’t it be great to test all edge cases in one go? Shouldn’t there be a logic written to make sure that functionality works properly without breaking anything? Don’t we all want to ship reliable and scalable features without sacrificing time? Don’t we want to test our features in different environments and different user interactions?” If the answer is yes, congratulations, you just learned the essence and importance of testing!

Software Reliability in different scenarios

Software reliability chart refers to how trustworthy and fault-tolerant your software is. As shown in the chart, the stability and reliability increase when we write code with the best conventions and cover all the edge cases. As a developer, we should always take responsibility for the code which we’ve written. For a feature to work seamlessly, we need to test such kind of fragile features in various kinds of environments and with various kinds of scenarios.

Introducing React Testing Library

React Testing Library is an open-source and lightweight testing library created by Kent C. Dodds, who is a well-known personality in the front-end industry. React Testing Library falls under the category of black box testing, which makes it different from other UI testing libraries. Rather than testing the internal mechanisms/know-how of the component it tests the functionality by simulating user interaction with your component(s).

Tweet by Kent on creating a new Testing Library

React Testing Library, at its core, works on a very simple yet profound philosophy 👇

The more your tests resemble the way your software is used, the more confidence they can give you.

The Approach

React Testing Library is a library package that provides helpful tools to test the React components by interacting with them rather than testing their implementation. Unlike other testing libraries, where the goal is to test the functionality of the components, this library emphasizes testing the UI directly by whatever updates are being rendered/visible on the screen. React Testing Library leverages the virtual DOM to render the DOM tree and supports testing of the components by interacting with them as your end user would interact.

React Testing Library is trying to solve a fundamental issue. Rather than handling the instances of already rendered React Components, we can skip such tricky solutions and test the actual DOM nodes to check the expected UI behavior. By directly testing the visual changes based on user interaction with the component, we can avoid writing fragile and brittle test cases that are less maintainable and not at all reliable.

Understanding React Testing Library

React Testing Library does not care about the implementation details of your components, but it cares about what visual changes it generates when the user interacts with the UI. For example, if you are familiar with other testing libraries, like enzyme, your test will break even when you change the name of the state related to the component since we test the functionality by sneaking into implementation directly. Fortunately, that’s not the case with React Testing Library. In simple words, your tests will continue to pass unless it triggers some unwanted or unexpected UI changes.

For querying and testing DOM nodes, React Testing Library provides a set of functions that can help with querying an element by text, label, aria-labels, and roles. Since React Testing Library actually renders the component using virtual DOM, the screen object provided by the library contains information about UI and visual changes.

This approach sounds familiar, right? Yes, that’s how the end user also interacts with the UI. That’s why we can say that this library provides a testing approach that is closer to user interaction, resulting in a boost of confidence while writing tests and maintaining tests. Furthermore, since this approach encourages us to test the generated or rendered output by querying with labels or text, it also encourages the developers to write accessible components.

Features of React Testing Library

React Testing Library comes with an ample amount of battle-tested functionalities developed by keeping developer experience in mind.

Some of the features of React Testing Library include 👇

  • Provides render method to render the React component with virtual DOM
  • Automatically re-renders the component as and when the state changes due to some user interaction
  • Built-in support for testing user interactions like clicking, double-clicking, typing, or hovering with fireEvent
  • Provides a range of query methods to access the information about the current state of the UI
  • Enforces testing conventions and best practices which helps us write maintainable and reliable tests
  • Out-of-the-box support for debugging tools
  • Automatically unmounts the rendered component and cleans up any associated resources to keep the test environment isolated and prevent memory leaks
  • Helps to eliminate the possibility of unwanted crashes
  • Support for testing react hooks with renderHook
  • Huge community support and fine-grained documentation
  • Can be integrated easily with modern test runners like Jest and Mocha

Conclusion

React Testing Library has proven to be one of the most useful libraries for improving the reliability and stability of React applications.

By keeping user interaction at the core and providing a wide range of features, React Testing Library helps developers write battle-tested code that eliminates the possibility of potentially unexpected behaviors and edge cases. As you integrate React Testing Library into your next project, remember that testing is all about developing stable applications that stand the test of time.

For more updates on the latest tools and technologies, follow the Simform Engineering blog.

Follow Us: Twitter | LinkedIn

--

--

Adarsh Pandya
Simform Engineering

Just a storyteller who tells the stories in form of blogs related to web developement ✨