Learn How To Test React Applications (Testing React Applications with Jest and React Testing Library)

How to test react applications with jest and react testing library. Image courtesy of morioh.com

Table Of Content

  1. TL;DR:
  2. Why Write Tests?
  3. Types of Testing
  4. Which Tests Should I Write?
  5. Which Testing Library/Framework Should I Use?
  6. React Testing Library vs Enzyme
  7. What Should We Test?
  8. Testing Terminology
  9. Test Anatomy
  10. Setup React With Jest and React Testing Library
  11. Writing React Tests With react-testing-library and Jest
  12. Write a testable App
  13. What Do We Want to Test (Test Cases)
  14. Write and run actual Tests
  15. Appendix

TL;DR:

Why Write Tests?

  1. Increase confidence that your project is bug free
  2. Avoid regression (avoid potentially breaking future changes).
  3. Ensure your application does what you want it to (enforce business logic).
  4. Your team lead forced you to 😃

Types of Testing

  1. Static Testing/Type Checking: Catch typos and type errors as you write code. This helps identify certain types of problems before you even run your code. Tools for this include static type checkers such as Flow and Typescript and linters such as eslint.
  2. Unit Testing: Verify that individual, isolated parts (Components) work as expected. That given certain inputs a component returns/renders/does expected results. Tools for this include Jest, enzyme and react testing library.
  3. Integration Testing: Verify that several units work together in harmony. For example, that an admin user is taken to the admin dashboard after login. Tools for this include Jest, enzyme and react testing library. Notice something?
  4. End to End Testing: A helper robot that behaves like a user to click around the app and verify that it functions correctly. Runs the tests like how a Q.A person would, on a real browser with a real back-end(or a stubbed one but hey!). Sometimes called functional testing or e2e. Tools for this include cypress.
  5. Scream Test: Read This article. And don’t @ me when you are fired 😃

Which Tests Should I Write?

Basically as you scale the testing ladder (Static ---> End-To-End) two things happen:

  1. Confidence that your application is bug free increases.
  2. Costs (Time and Money) increases.

Which Testing Library/Framework Should I Use?

Now that we know we should prioritize Integration testing (and that the line between integration and unit testing is fuzzy), which testing libraries/utilities should we use? Let’s break down the alternatives

  1. Jest - Jest is a complete JavaScript testing framework created and maintained by Facebook. Jest can be used as is for complete integration testing, however, it is generally used as a test runner, assertion and mocking framework. More on testing terminology later.
  2. Enzyme - Enzyme is a JavaScript Testing library for React created by AirBnB. Unlike Jest, Enzyme does not ship with test running, mocking, or assertion functionality (normally used with Jest for that). Enzyme is normally used for app/component rendering, DOM node(s) query, and event simulation. I promise testing terminology are covered below.
  3. React Testing Library - Like Enzyme. Used for app/component rendering, DOM node(s) query, and event simulation.

React Testing Library vs Enzyme

For me, it boils down to each library’s primary guiding principle:

  1. React Testing Library - The more your tests resemble the way your software is used, the more confidence they can give you.
  2. Enzyme - To be intuitive and flexible by mimicking jQuery’s API for DOM manipulation and traversal.
  1. The guiding principle of testing your software the way it’s being used (by real users) increases confidence in your app being bug free in production. Not only is this principle supported, it’s enforced. This enforces a different mindset as you test your application. The best thing about this mindset change is that you are thinking about your users within your tests, thinking about how they interact with it rather than thinking about how the props and state objects look (implementation).
  2. By not testing implementation details (stand alone components, state, props, and functions), your tests will survive implementation overhaul and will not break if implementation change but assertions hold. Focusing on testing users behavior rather than the implementation allows you to easily refactor code going forward. You want your user experience to be the same regardless of your implementation details.
  3. Due to the strict use case/philosophy, there’s only a couple of queries and helpers baked in, this makes the library extremely lightweight and minimal.
  4. The library makers provide a custom jest matchers library (jest-dom) that is aligned to the libraries guiding principle.

What Should We Test?

Two things:

  1. Use Case Coverage > Code Coverage
  2. The more your tests resemble the way your software is used, the more confidence they can give you.

Testing Terminology

  1. Software Testing: A process, to evaluate the functionality of a software application with an intent to find whether the developed software meet the specified requirements or not and to identify the defects to ensure that the product is defect-free in order to produce a quality product.
  2. Test runner: A library or tool that picks up software tests in a source code directory and then executes them and writes the test results to the console or log files. Like Jest
  3. Test Suite: A collection of test cases that are intended to be used to test a software program to show that it has some specified set of behaviors. Like Jest’s Describe Block
  4. Test Setup and Teardown: Setup work that needs to happen before and after tests run. Like Jest’s beforeEach and afterEach
  5. Test Case: A specification of the inputs, execution conditions, testing procedure, and expected results that define a single test to be executed to achieve a particular software testing objective. Multiple test cases make up a single Test Suite. Like Jest’s it/test block
  6. Mocking: Creating objects that simulate the behavior of real objects(including functions, props, react hooks e.t.c). Like Jest Mocks
  7. Render/Execution: execute the software being tested in an artificial environment. Like react-testing-library’s render function and JSDOM
  8. DOM node queries: Utility to query for DOM nodes/elements. Like react-testing-library’s getByText, queryByText and getByRole.
  9. Assertion: An expression which encapsulates some testable logic specified about a target under test. Has the anatomy: expect(selector/query).matcher function (i.e expect (a certain element).to have a certain property).
  10. Expect block: Represents a test assertion. Like Jest’s expect block
  11. Matcher Function: Represents a test expectation. Like Jest-dom’s toBeInTheDocument()
  12. Actions: such as firing events or calling functions. like react-testing-library’s fireEvent

Test Anatomy

See the gist below. Citations and annotations available inline.

A Jest and React Testing Library Test Anatomy Example

Setup React With Jest and React Testing Library

Disclaimer/Prerequisite:

  • We are going to use the create-react-app cli for bootstrapping (which ships with Jest pre-installed). For manual React, Webpack, Babel setup there are tutorials for setup from scratch out there. Like this one
  • It is assumed that you have Node.js and Yarn package manager installed.
  • I prefer to name my unit tests with “it” instead of “test” but you could use either.

Steps:

  1. cd into your projects folder and create a new React project.
npx create-react-app react_jest_react_testing_library #npx is an npm package runner that ships with npm
cd react_jest_react_testing_library
code . #for vscode
yarn add --dev @testing-library/react @testing-library/jest-dom 
setup custom jest extensions with react testing library
yarn test
successful tests for the default create-react-app template
successful tests for the default create-react-app template

Writing React Tests With React-Testing-Library and Jest

0. Write a Testable App

Let’s write a simple app to be used as our test prototype.

Track logged in state and update displayed info accordingly. Also generate random Quotes
Toggle content depending on the logged in and logged out states
Toggle content depending on the logged in and logged out states
Custom react hook to fake network calls for logging in and out.
Return one of eleven quotes randomly

1. What Do We Want to Test (Test Cases)?

  1. Default State: By default, it shows “You are Logged out!”, a button with “Log In” text, a button with “Generate Random Quote” text, and no quote.
  2. Generating Quote: When you click the “Generate Random Quote” button, a new quote is shown and when you click again a different one is shown.
  3. Log In Process: When you click on the “Log In” button, it changes text to “Loading…” and shows the login state as “You are …”. The button then finally changes to “Log Out” and the text to “You are Logged In!”
  4. Log Out Process: When you click on the “Log Out” button, it changes text to “Loading…” and shows the login state as “You are …”. The button then finally changes to “Log In” and the text to “You are Logged out!”

2. Write and Run Actual Tests

N/B: Since we are testing the user behavior (Cases coverage) and not the implementation (Code Coverage), you can safely ignore the utils and components folder and instead concentrate on what the DOM tree renders (what the app renders when you yarn start). You can write test cases for the app without ever looking at the implementation!.

  1. I had to bump the pre-installed react testing library and jest-dom to the latest versions and install jest-environment-jsdom-sixteen to make waitFor and waitForElementToBeRemoved which are new to the API work. You Probably don’t need to because this is in the future and the create react app developers have bumped up the internals. If so, skip steps 1 and 2 and head to step 3.
yarn add jest-environment-jsdom-sixteen --dev && yarn add --dev @testing-library/react @testing-library/jest-dom
“test”: “react-scripts test — env=jest-environment-jsdom-sixteen”,
Test cases
yarn test
Passing Tests

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store