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://jestjs.io//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!