Detailed Guide to React App Testing

Key Takeaways

  1. React app testing is crucial for delivering secure, high-performing, and user friendly application.
  2. React Apps are created using different UI components. So it is necessary to test each component separately and also how they behave when integrated.
  3. It is essential to involve Unit Testing, Integration Testing, End-to-End Testing, and SnapShot Testing for a React app as per the requirements.
  4. React Testing Library, Enzyme, Jest, Mocha, Cypress, Playwright, Selenium,  JMeter, Jasmin and TestRail are some of the key tools and libraries used for testing React app.

React is a prominent JavaScript library that is used by app development companies to create unique and robust applications. It comes with a declarative style and gives more emphasis on composition. With the help of this technology, every React app development company in the market can transform their client’s business by creating modern web applications. When businesses grow, the size of the web application along with its complexity will grow for which the development team will have to write tests that can help in avoiding bugs.

Though testing React apps isn’t an easy task, some frameworks and libraries can make it possible for the development teams. In this article, we will go through such libraries.

1. Why do We Need to Test the Web App?

The main reason behind testing applications is to ensure that the apps work properly without any errors. Along with this, in any application, several features might require some attention from the developers as they might cause expensive iterations if not checked frequently. Some of the areas where testing is a must are:

  • Any part of the application that involves getting input from the user or retrieving data from the application’s database and offering that to the user.
  • The features of the application that are connected with call-to-action tasks where user engagement becomes necessary, need to be tested.
  • When any sequential event is being rendered as its elements lead to function, testing is required.

2. What to Test in React App?

Developers often get confused about what to test in a React application. The reason behind this confusion is that applications are generally dealing with simple data but sometimes they are quite sophisticated. In any case, developers need to set their priorities for testing the applications. Some of the best things to start the testing process with are:

  • Identifying the widely used React components in the applications and start testing them.
  • Identifying application features that can help in adding more business value and adding them for testing.
  • Executing border case scenarios in high-valued features of React application.
  • Performance and stress testing applications if they are serving a large number of users like Amazon or Netflix.
  • Testing React hooks.

3. Libraries and Tools Required

React test libraries and frameworks can be beneficial to offer the best application to the end users. But all these frameworks have their specialty. Here we will have a look at some of these React testing libraries and tools for React application testing.

3.1 Enzyme

EnzymeJS

Enzyme is a React testing library that enables React app developers to traverse and manipulate the runtime of the output. With the help of this tool, the developers can carry out component rendering tasks, find elements, and interact with them. As Enzyme is designed for React, it offers two types of testing methods: mount testing and shallow rendering. This tool is used with Jest.

Some of the benefits of Enzyme are:

  • Supports DOM rendering.
  • Shallow rendering.
  • React hooks.
  • Simulation during runtime against output.

3.2 Jest

JestJS

Jest is a popular React testing framework or test runner suggested by the React community. The testing team prefers this tool to test applications for large-scale companies. Firms like Airbnb, Uber, and Facebook are already using this tool.

Some of the benefits of Jest are:

  • Keeps track of large test cases.
  • Easy to configure and use.
  • Snapshot-capturing with Jest.
  • Ability to mock API functions.
  • Conduct parallelization testing method.

3.3 Mocha

MochaJS

It is also a widely used testing framework. Mocha runs on Node.js and testers use it to check applications that are developed using React. It helps developers to conduct testing in a very flexible manner.

Here are some of the benefits of Mocha:

  • Easy async testing.
  • Easy test suite creation.
  • Highly extensible for mocking libraries.

3.4 Jasmine

Jasmine

Jasmine is a simple JavaScript testing framework for browsers and Node.js. Jasmine comes with a behavior-driven development pattern which means that using this tool can be a perfect choice for configuring an application before using it. Besides this, third-party tools like Enzyme can be used while working with Jasmine for testing React applications. 

Some of Jasmine’s benefits include:

  • No DOM is required.
  • Asynchronous function testing.
  • Front-end and back-end testing is possible.
  • Inbuilt matcher assertion.
  • Custom equality checker assertion.

Despite its many benefits, Jasmine isn’t the perfect testing framework for React apps. It doesn’t offer support for testing snapshots. For this, it requires the usage of third-party tools.

4. How to Test React Applications?

Here are the steps that can help you test a React application. 

4.1 Build a Sample React App

First of all, we will create a minimal application that displays users’ information from an API. This application will be then tested to see how React app testing works. 

Here, as we only have to focus on the front end of the application, we will use JSONPlaceholder user API. First of all, the developer needs to write the following code in the App.js file:

import { useEffect, useState } from "react";
import axios from "axios";
import { getFormattedUserName } from "./utility";
import "./App.css";
 
 
function App() {
  const [users, setUsers] = useState([]);
 
 
  // Fetch the data from the server
  useEffect(() => {
    let isMounted = true;
    const url = "https://jsonplaceholder.typicode.com/users";
    const getUsers = async () => {
      const response = await axios.get(url);
      if (isMounted) {
        setUsers(response.data);
      }
    };
    getUsers();
  }, []);
 
 
  return (
    <div>
      <h1>Users:</h1>
      <ul>
        {users.map((user) => {
          return (
            <li key={user.id}>
              {user.name} --{" "}
              <span>({getFormattedUserName(user.username)})</span>
            </li>
          );
        })}
      </ul>
    </div>
  );
}
 
 
export default App;

Then, it is time to create a file in the src folder. Name the file utility.js and write the following function in it:

export function getFormattedUserName(username) {
  return "@" + username;
}

Now, run the application using this command:

npm start

Once you run the application, you will see the following output:

User List- Output

4.2 Unit Testing

Now, let’s start with testing the application that we have just developed. Here we will start with unit testing. It is a test for checking individual software units or React components separately. A unit in an application can be anything from a routine, function, module, method, and object. Whatever the test objective the testing team decides to follow specific if the unit testing will offer the expected results or not. A unit test module contains a series of approaches that are provided by React development tools like Jest to specify the structure of the test. 

To carry out unit testing, developers can use methods like test or describe as the below-given example:

describe('my function or component', () => {
 test('does the following', () => {
   // add your testing output
 });
});

In the above example, the test block is the test case and the described block is the test suite. Here, the test suite can hold more than one test case but a test case doesn’t need to be present in a test suite. 

When any tester is writing inside a test case, he can include assertions that can validate erroneous or successful processes. 

In the below example, we can see assertions being successful:

describe('true is truthy and false is falsy', () => {
 test('true is truthy', () => {
   expect(true).toBe(true);
 });
 
 test('false is falsy', () => {
   expect(false).toBe(false);
 });
});

After this, let us write the first test case that can target the function named

getFormattedUserName

from the utilitymodule. For this, the developer will have to build a file called utility.test.js. All the test files use this naming pattern: {file}.test.js, there {file} is the module file name that needs to be tested. 

In this code, the function will take a string as an input and will offer the same string as an output by just adding an @ symbol at its beginning. Here is an example of the same:

import { getFormattedUserName } from "./utility";
 
 
describe("utility", () => {
  test("getFormattedUserName adds @ at the start beginning of the username", () => {
    expect(getFormattedUserName("jc")).toBe("@jc");
  });
});

As seen in the above code, any tester can easily specify the module and test case in the code so that if it fails, they can get an idea about the things that went wrong. As the above code states, the first test is ready, so the next thing to do is run the test cases and wait for the output. For this, the tester needs to run a simple npm command:

npm run test

After this, one will have to focus on running tests in a single test with the use of the following command:

npm run test -- -t utility

This can be done when there are other tests created by create-react-app. If by running the above commands, everything goes well, you will be able to see an output like this:

Unit test Output

Successful output.

Here, in the output, you can observe that one test passed successfully. But if in this case, something goes wrong, then a new test needs to be added to the utils test suite. For this, the below-described code can be useful:

test('getFormattedUserName function does not add @ when it starts with @is already provided', () => {
    expect(getFormattedUserName('@jc')).toBe('@jc');
  });

This will be a different situation. In this case, if the username already has an @ symbol at the start of the string, then the function will return the output as the username was provided without any other symbol. Here is the output for the same:

Failed Unit Test

Failed test output.

As anticipated, the test failed as the information the system received was the expected value as the output. Here, if the tester can detect the issue, he can also fix it by using the following code:

export function getFormattedUserName(username) {
  return !username.startsWith("@") ? `@${username}` : username;
}

The output of this code will be:

Unit Test Successful

As you can see, the test is a success.

4.3 SnapShot Testing

Now, let us go through another type of testing which is Snapshot testing. This type of test is used by the software development teams when they want to make sure that the UI of the application doesn’t change unexpectedly.

Snapshot testing is used to render the UI components of the application, take its snapshot, and then compare it with other snapshots that are stored in the file for reference. Here, if the two snapshots match, it means that the test is successful, and if not, then there might have been an unexpected change in the component. To write a test using this method, the tester needs the react-test-renderer library as it allows the rendering of components in React applications. 

The very first thing a tester needs to do is install the library. For this, the following command can be used:

npm i react-test-renderer

After this, it’s time to edit the file to include a snapshot test in it.

import renderer from "react-test-renderer";
 
// ...
 
test("check if it renders a correct snapshot", async () => {
  axios.get.mockResolvedValue({ data: fakeUserData });
  const tree = renderer.create(<App />).toJSON();
  expect(tree).toMatchSnapshot();
});
 
 
// ...

When the tester runs the above code, he will get the following output.

SnapShot Test Output

When this test runs, a test runner like Jest creates a snapshot file and adds it to the snapshots folder. Here is how it will look:

// Jest Snapshot v1, https://goo.gl/fbAQLP
 
exports[`check if it renders a correct snapshot 1`] = `
<div>
  <h1>
    Users:
  </h1>
 
    Loading user details...
  </div>
</div>
`;

Now, if one wants to modify the App component, only one single text value needs to be changed. Here, the correct snapshot test will be rendered to fail as there will be a change in the output.

Renders Correct Snapshot

To make the test successful, the tester needs to inform a tool like Jest about the intentional changes. This can be easily carried out when Jest is in watch mode. The snapshot as shown below will be taken:

SnapShot Test Successful

4.4 End-to-end Testing

Another popular type of React application testing is end-to-end testing. In this type of testing, the entire system is included. Here all the complexities and dependencies are considered. In general, UI tests are difficult and expensive which is why end-to-tests are carried out rather than unit tests that focus on only the critical parts of the applications. This type of testing comes with various approaches:

  • Usage of platform for automated end-to-end testing.
  • Automated in-house end-to-end testing.
  • Usage of platform for manual end-to-end testing.
  • Manual in-house end-to-end testing.

4.5 Integration Testing

Now, we will go through integration testing which is also considered an essential type of react application testing. It is done to ensure that two or more modules can work together with ease.

For this, the software testing team will have to follow the below-given steps:

First of all, one needs to install the dependencies with yarn by using the following command:

yarn add --dev jest @testing-library/react @testing-library/user-event jest-dom nock

Or if you want to install it with npm, use this command line:

npm i -D jest @testing-library/react @testing-library/user-event jest-dom nock

Now, it’s time to create an integration test suite file named viewGitHubRepositoriesByUsername.spec.js. For this, Jest will be useful to automatically pick it up.

Now, import dependencies using the code:

import React from 'react'; // so that we can use JSX syntax
import {
 render,
 cleanup,
 waitForElement
} from '@testing-library/react'; // testing helpers
import userEvent from '@testing-library/user-event' // testing helpers for imitating user events
import 'jest-dom/extend-expect'; // to extend Jest's expect with DOM assertions
import nock from 'nock'; // to mock github API
import {
 FAKE_USERNAME_WITH_REPOS,
 FAKE_USERNAME_WITHOUT_REPOS,
 FAKE_BAD_USERNAME,
 REPOS_LIST
} from './fixtures/github'; // test data to use in a mock API
import './helpers/initTestLocalization'; // to configure i18n for tests
import App from '../App'; // the app that we are going to test

After that, you can set the test suite by following this code

describe(check GitHub repositories by username', () => {
 beforeAll(() => {
   nock('https://api.github.com')
     .persist()
     .get(`/users/${FAKE_USERNAME_WITH_REPOS}/repos`)
     .query(true)
     .reply(200, REPOS_LIST);
 });
 
 afterEach(cleanup);
 
 describe('if a user of GitHub has public repositories', () => {
   it('Users can view the list of public repositories by entering their GitHub username.', async () => {
     // arrange
     // act
     // assert
   });
 });
 
 
 describe('when a user on GitHub doesn't have any public repos', () => {
   it('The user is informed that the login provided for GitHub does not have any public repositories associated with it.', async () => {
     // arrange
     // act
     // assert
   });
 });
 
 describe('when logged in user does not exist on Github', () => {
   it('user is presented with an error message', async () => {
     // arrange
     // act
     // assert
   });
 });
});

5. Conclusion

As seen in this blog, to conduct React app testing, the testing team needs to have a proper understanding of the React testing libraries and tools. After that, they need to find out what React testing is needed for. This can help them choose the right tool from the above-listed ones.

FAQs

How is React testing conducted?

When it comes to React app testing, developers and testers can support the development of high-quality software along with features that can help developers reduce their time in making changes to the development and help testers create a dependable test suite.

Is React testing library Jest?

React Testing Library and Jest are two different things. Jest is a tool that helps in writing tests which can be beneficial for components of any application. 

Where can a React code be tested?

To test a React code, testers can use any tool like React Testing Library (RTL) and Enzyme. The choice depends on the application type and testing that is required for it.

profile-image
Vishal Shah

Vishal Shah has an extensive understanding of multiple application development frameworks and holds an upper hand with newer trends in order to strive and thrive in the dynamic market. He has nurtured his managerial growth in both technical and business aspects and gives his expertise through his blog posts.

Related Service

Know More about React Development Services

Learn More

Want to Hire Skilled Developers?


    Comments

    • Leave a message...