Divine is a software engineer passionate about building fast, scalable web apps with beautiful user interfaces and seamless experiences.
Published on
The React community is full of developers who are passionate about maintaining good development practices through testing. Many great tools and techniques are available to help you write tests for your React application, but to do it properly; you have to follow best practices.
This guide discusses the basics of testing in React, including why it is crucial, which tools are available, and the best practices for writing tests.
Testing is the process of verifying that something meets the provided requirements and produces the desired results. In programming, this means ensuring that your code works as expected.
There are two ways to test your application:
This type of testing is when a human performs tests step-by-step on an application without the aid of testing tools and scripts. QA analysts often use this approach when handling complex test cases that are not feasible to automate or involve scenarios that can only be validated once in a while.
Involves writing scripts that automatically check your code to ensure that the predefined conditions are correctly met. It handles multiple test cases that are easy to predict or tend to be validated repeatedly.
As humans, we are prone to mistakes and occasional errors. When building software, some of these mistakes go unnoticed and make it to production, where they could result in minor glitches or massive bugs with severe consequences. It is essential to test your application before it goes live to avoid such situations.
Some other reasons for testing include the following:
Testing has come a long way; over the years, different principles have emerged on how developers should write tests. A modern, excellent guide to follow while testing your React application is using the “Testing Trophy” proposed by Kent C. Dodds. It broadly outlines four types of tests: static, unit, integration, and end-to-end (e2e) tests.
These tests help to keep your codebase clean by scanning for minor errors like typos or missing semi-colons. They can also provide hotfixes to improve your productivity. Popular tools for static testing include Prettier, ES Lint, and Mocha.
Write unit tests when you want to independently test each small, isolated piece of your code. These tests give you a granular view of your code’s performance and can run very fast since they are so small. They are frequently used in Test Driven Development (TDD), where you first write the test, then write your code to pass it.
Integration tests ensure that different components in your React application work together and interact properly. This type of testing is advantageous when collaborating with other developers on a project, as you will have different people working on various components. With integration tests, you can verify that these components work well together and even work with third parties such as APIs and databases.
These tests are usually performed after building your application. They test your application’s workflow from beginning to end, replicating user scenarios and checking for things like hardware, external dependencies, databases, and network connectivity.
There are several testing tools available for React. Here are a few popular ones:
This JavaScript testing framework provides utilities for mocking data and replaying events, which can be very useful in unit tests. It is beginner-friendly and does not require a lot of configuration for first-time users.
Its features include:
This testing utility tool adds APIs for working with React components to the DOM Testing Library. All React projects created with create-react-app have React Testing Library by default.
Its features include:
This open-source test runner is written in Node.js. Every release of Mocha contains a mocha.js and mocha.css file and allows you to test asynchronous JavaSript in your browser.
Some of its other features include:
Cypress is a popular open-source JavaScript framework for running end-to-end tests. It works for all programming languages, platforms, and browsers.
Its features include:
Automatically waiting for commands and assertions. This feature helps to prevent async issues.
Here are some best practices for testing React apps:
When building your React application, your codebase will be classified into two major parts:
If you write tests for a variable name (an implementation detail) and later update the variable name in your code without updating the tests, your code will still work as expected, but the tests will fail. This scenario is known as a false-negative.
Assume you did not change the variable name, but you have a function to display some text on the screen when the user clicks a button, and you did not call that function correctly (bad functionality). If you run tests on your implementation detail, it will pass, but your application will fail in production because its functionality is faulty. This scenario is known as a false-positive.
To avoid scenarios like these, it is better to test for functionalities that reflect how your end-user will use the app since these expectations rarely change no matter what updates you make to your codebase.
In your React application, you will build many components that interact differently. For example, a button component can work with a contact form to get and upload user data, and the same button will work as a call-to-action on the homepage.
To ensure that these integrations work as expected, you should write integration tests to check how your components interact with each other in different contexts and scenarios and even with external APIs.
When writing tests for your React application, to avoid conflicts and ensure that all the essential parts of your app are thoroughly tested, it is best to have a list of things to test for and go through the list one item at a time.
This practice will help to keep your test suites smaller and more manageable so that changes are easier to spot during code review.
Consider this example below:
In the code above, you test to see if a modal displays a message. For the modal to display that message, it has to be visible, so the first test is unnecessary and can be safely removed.
Developers are often encouraged to aim for 100% code coverage, but this could lead you down a rabbit hole and make you spend more time writing unnecessary tests. It could also result in missing out on important scenarios likely to have defects because you aim to ensure that each line of code is tested.
It is best to focus on writing tests that truly matter to ensure your application works as intended, then continuously improve on that code and its tests.
Testing is an essential part of the development process. However, if you test for the wrong things - or even worse, don’t test at all - you will spend too much time trying to figure out why something is not working correctly.
Get visual proof, steps to reproduce and technical logs with one click
Continue reading
Try Bird on your next bug - you’ll love it
“Game changer”
Julie, Head of QA
Try Bird later, from your desktop