×
By the end of this chapter, you should be able to:
jest
Jest is a wonderful testing library created by Facebook to help test JavaScript code, React components, and much more. What's great about Jest is it not only is included with create-react-app
(you can read more about that here), but with Jest your tests run in parallel so they are executed much faster than other testing frameworks.
Also, Jest syntax is extremely familiar if you've ever used:
So you won't have to learn much to switch to Jest!
So let's create a new React application write some simple tests!
We can use Jest without React, so it's important to understand how that works. Before we start testing our components, let's write some simple specs with Jest and see how the built in test
and expect
functions work.
Let's first get started with a simple create-react-app
application. In the terminal, go ahead and write:
create-react-app learn-testing && cd learn-testing
Inside of here we can run our specs by typing npm test
and we will see that we have one spec passing - here's what you should see:
PASS src/App.test.js ✓ renders without crashing (25ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.393s Ran all test suites related to changed files. Watch Usage › Press p to filter by a filename regex pattern. › Press t to filter by a test name regex pattern. › Press q to quit watch mode. › Press Enter to trigger a test run.
Notice here that we are in watch mode which will constantly look for changes in our test files. The one passing test is coming from src/App.test.js
, the starter test file you get whenever you create a project with create-react-app
. The inside of that file should look like this:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; it('renders without crashing', () => { const div = document.createElement('div'); ReactDOM.render(<App />, div); });
We can see here that we easily can test that the application has rendered, but before we jump into testing our components, let's get to learn jest
a bit better. Start by making a file called learn.test.js
in our src
directory. Inside of this file, add the following:
test('it works', function() { expect(1).toBe(1); });
Notice that we are using the word test
on the first line. You can use the it
and describe
keywords if you'd like as well!
Jest has quite a few functions used for assertions/expectations. You can see a full list here, but here are some common ones.
toBeDefined
toBeGreaterThan / toBeLessThan
toBe
(uses === to compare)toEqual
(for deep object comparison)toContain
(see if a value is inside of a collection)Let's try out a few more examples of the syntax in learn.test.js
:
test('arithmetic', function() { expect(4 + 4).toBeGreaterThan(7); expect(4 + 4).toBeLessThan(9); }); test('references', function() { var arr = [1, 2, 3]; expect(arr).toEqual([1, 2, 3]); expect(arr).not.toBe([1, 2, 3]); // since === doesn't do deep comparison! expect(arr).toContain(1); });
You also might not want to place all of your test files with your files in the src
folder. In order for Jest to read your tests, place them in a folder called __tests__
inside of the src
folder.
Make sure that your folder is called __tests__
- this is essential! Inside of the __tests__
folder we can place all of the files that we'd like Jest to run.
Now that we have a basic understanding of how to use Jest, let's discuss a nice feature it provides called Snapshot Testing.
Imagine for a second we have a component that looks like this
import React from 'react'; const SimpleComponent = ({ first, last, favFood }) => ( <div> <h1>Hello there!</h1> <h2>Welcome!</h2> <p>First Name - {first}</p> <p>Last Name - {last}</p> <p>Favorite Food - {favFood}</p> </div> ); export default SimpleComponent;
If we wanted to test this component we could write all the specs to make sure that when we render the component there are three paragraph tags, one h1
tag and that props are being correctly set on the component.
However, when one small change is made to our UI, this test will fail and we'll have to go edit the test again to account for new UI changes. This process is quite tedious. Fortunately, Jest has an excellent alternative: snapshot testing.
The way snapshot testing works is that Jest will take a snapshot of your component and when future tests are run, it will alert you of any differences between the current snapshot and a previous one. If you would like to update the snapshot, you can simply add a -u
flag and update with a new snapshot.
Snapshot testing does not cover all cases. There will be times where you want to test the functionality of a component rather than its appearance. But when testing stateless functional components, snapshot testing is esspecially useful since you don't anticipate these components changing frequently.
Enough about Snapshot testing - let's see the code! First, we'll need to install another module, called `react-test-renderer, which is necessary for rendering our components while testing.
npm i --save-dev react-test-renderer
Next, in our src
folder, let's create a new file called SimpleComponent.js
and place the following code:
import React from 'react'; const SimpleComponent = ({ first, last, favFood }) => ( <div> <h1>Hello there!</h1> <h2>Welcome!</h2> <p>First Name - {first}</p> <p>Last Name - {last}</p> <p>Favorite Food - {favFood}</p> </div> ); export default SimpleComponent;
Now in our __tests__
folder, let's add the following code in a file called SimpleComponent.test.js
:
import React from 'react'; import SimpleComponent from '../SimpleComponent'; import renderer from 'react-test-renderer'; describe('<SimpleComponent />', () => { it('matches the snapshot', () => { var tree = renderer.create(<SimpleComponent />).toJSON(); expect(tree).toMatchSnapshot(); }); });
When we run npm test
we should see everything passing! We can also see that in our __tests__
folder, a folder called __snapshots__
has been created. In here, we can see our SimpleComponent.test.js.snap file which looks like this:
// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`<SimpleComponent /> matches the snapshot 1`] = ` <div> <h1> Hello there! </h1> <p> First Name - </p> <p> Last Name - </p> <p> Favorite Food - </p> </div> `;
This is the saved snapshot! Now let's go and edit our SimpleComponent.js
file and insert a new h2
which says Welcome! And let's see what happens with our test. We now see that there is a failing test because the snapshots are different! So we are faced with two choices here
go fix the component because this UI change is not something we wanted
or
update the snapshot to include our new UI
In our terminal, there is an option for us to press u
to update the snapshot, so let's do that and we should see the tests are passing again!
In summary, snapshot testing is fantastic as a really quick and easy way to test the UI of components. Learn more about it here.
When you're ready, move on to Testing with Enzyme