This post is part of the series 30 Days of React.

In this series, we're starting from the very basics and walk through everything you need to know to get started with React. If you've ever wanted to learn React, this is the place to start!

Implementing Tests

Edit this page on Github

Yesterday we examined the different types of tests that we write in React. Today we'll see it in action. We'll install the dependencies required to set up tests as well as write our first assertions.

Let's get our application set up to be tested. Since we're going to be using a few different libraries, we'll need to install them before we can use them (obviously).

Dependencies

We're going to use the following npm libraries:

jest/jest-cli

Jest is the official testing framework released by Facebook and is a fantastic testing framework for testing React applications. It is incredibly fast, provides sandboxed testing environments, support for snapshot testing, and more.

babel-jest/babel-preset-stage-0

We'll write our tests using the stage 0 (or ES6-edge functionality), so we'll want to make sure our test framework can read and process our ES6 in our tests and source files.

sinon

Sinon is a test utility library which provides a way for us to write spies, stubs, and mocks. We'll discuss what these are when we need them, but we'll install the library for now.

react-addons-test-utils/enzyme

The react-addons-test-utils package contains testing utilities provided by the React team.

Enzyme, a JavaScript testing library built/maintained by Airbnb is a bit easier to work with and provides really nice methods for traversing/manipulating React's virtual DOM output. While we'll start with react-addons-test-utils, we'll transition to using Enzyme as we prefer using it in our tests.

react-test-renderer

The react-test-renderer library allows us to use the snapshot feature from the jest library. Snapshots are a way for Jest to serialize the rendered output from the virtual DOM into a file which we can automate comparisons from one test to the next.

redux-mock-store

The redux-mock-store library allows us to easily make a redux store for testing. We'll use it to test our action creators, middleware, and our reducers.

To install all of these libraries, we'll use the following npm command in the terminal while in the root directory of our projects:

yarn add --dev babel-jest babel-preset-stage-0 enzyme enzyme-adapter-react-16 jest-cli react-addons-test-utils react-test-renderer redux-mock-store sinon

Configuration

We'll also need to configure our setup. First, let's add an npm script that will allow us to run our tests using the npm test command. In our package.json file in the root of our project, let's add the test script. Find the scripts key in the package.json file and add the test command, like so:

{
  // ...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "eject": "react-scripts eject",
    "test": "react-scripts test --env=jsdom"
  },
}

Writing tests

Let's confirm that our test setup is working properly. Jest will automatically look for test files in the entire tree in a directory called __tests__ (yes, with the underscores). Let's create our first __tests__ directory in our src/components/Timeline directory and create our first test file:

mkdir src/components/Timeline/__tests__
touch src/components/Timeline/__tests__/Timeline-test.js

The Timeline-test.js file will include all the tests for our Timeline component (as indicated by the filename). Let's create our first test for the Timeline component.

We'll write our tests using the Jasmine framework. Jasmine provides a few methods we'll use quite a bit. Both of the following methods accept two arguments, the first being a description string and the second a function to execute:

  • describe()
  • it()

The describe() function provides a way for us to group our tests together in logical bundles. Since we're writing a bunch of tests for our Timeline, we'll use the describe() function in our test to indicate we're testing the Timeline.

In the src/components/Timeline/__tests__/Timeline-test.js file, let's add the describe block:

describe("Timeline", () => {});

We can add our first test using the it() function. The it() function is where we will set our expectations. Let's set up our tests with our first expectations, one passing and one failing so we can see the difference in output.

In the same file, let's add two tests:

describe("Timeline", () => {
  it("passing test", () => {
    expect(true).toBeTruthy();
  });

  it("failing test", () => {
    expect(false).toBeTruthy();
  });
});

We'll look at the possible expectations we can set in a moment. First, let's run our tests.

Executing tests

The create-react-app package sets up a quality testing environment using Jest automatically for us. We can execute our tests by using the yarn test or npm test script.

In the terminal, let's execute our tests:

yarn test

From this output, we can see the two tests with one passing test (with a green checkmark) and one failing test (with the red x and a description of the failure).

Let's update the second test to make it pass by changing the expectation to toBeFalsy():

describe("Timeline", () => {
  it("passing test", () => {
    expect(true).toBeTruthy();
  });

  it("failing test", () => {
    expect(false).toBeFalsy();
  });
});

Re-running the test, we can see we have two passing tests

yarn test

Expectations

Jest provides a few global commands in our tests by default (i.e. things you don't need to require). One of those is the expect() command. The expect() command has a few expectations which we can call on it, including the two we've used already:

  • toBeTruthy()
  • toBeFalsy()
  • toBe()
  • toEqual()
  • toBeDefined()
  • toBeCalled()
  • etc.

The entire suite of expectations is available on the jest documentation page at: https://facebook.github.io/jest/docs/api.html#writing-assertions-with-expect.

The expect() function takes a single argument: the value or function that returns a value to be tested. For instance, our two tests we've already writen pass the boolean values of true and false.

Now that we've written our first tests and confirmed our setup, we'll actually get down to testing our Timeline component tomorrow. Great job today and see you tomorrow!

Learn React the right way

The up-to-date, in-depth, complete guide to React and friends.

Download the first chapter

Ari Lerner

Hi, I'm Ari. I'm an author of Fullstack React and ng-book and I've been teaching Web Development for a long time. I like to speak at conferences and eat spicy food. I technically got paid while I traveled the country as a professional comedian, but have come to terms with the fact that I am not funny.

Connect with Ari on Twitter at @auser.