Getting Started Testing With Jest


As if we don't have enough new tech in our stack at this point, I'm going to use Jest - Facebook's JavaScript test framework - as our test tool in this project.

I've deliberately chosen Jest as our stack is already heavily Facebook-friendly, and it makes the most sense (to me, at least) to use the tools that FB use, as they deal with React at scales vastly larger than I ever will. And if it works for them...

Honestly though, if you have any experience at all with JavaScript testing (especially Jasmine / Mocha), the syntax for Jest should feel extremely familiar. And if you've never done testing before, hopefully you will see that not only is it easy to get started, it also makes writing code that works first time a lot more commonplace.

Adding Jest to our project is easy enough:

yarn add -D jest

And then we need to update the test script inside package.json to use Jest rather than anything else you might already have configured:

// /package.json

  "scripts": {
    "test": "jest"
  },

And with that, you should be good to run yarn test to trigger a test suite run.

Once that works, it's nice to add two more things in here.

The first is to have a test watcher, so if you change any files, the tests will automatically re-run:

// /package.json

  "scripts": {
    "test": "jest",
    "test:watch": "npm run test -- --watch"
  },

Then instead of running yarn test, you need to run yarn test:watch.

And also, I like to have some coverage information output:

// /package.json

  "scripts": {
    "test": "jest --coverage",
    "test:watch": "npm run test -- --watch"
  },

I follow the convention of putting all my tests in /__tests__, and have a directory structure under the __tests__ directory that mirrors my src dir.

That is to say, if I have a src/reducers/requestReducer.js file, then I would have a __tests__/reducers/requestReducer.react-test.js file to match it. I use the *.react-test.js suffix to distinguish between the real and test files, to avoid any accidents during import.

With that we are good to start writing some tests.

Basic Reducer Tests

The video covers this in further depth, so I'm going to do the "code speaks a thousand words" approach here, and simply show you the final test file as of at the end of this video.

// /__tests__/reducers/requestReducer.react-test.js

import request from '../../src/reducers/requestReducer';
import {SENDING_REQUEST} from '../../src/constants/actionTypes';

describe('Request Reducer', () => {

  it('has a default state', () => {
    expect(request(undefined, { type: 'unexpected'})).toEqual({
      sendingRequest: false
    });
  });

  it('can handle SENDING_REQUEST', () => {
    expect(request(undefined, {
      type: SENDING_REQUEST,
      payload: {
        sendingRequest: true
      }
    })).toEqual({
      sendingRequest: true
    });
  });

});

The key thing to take away here is that we are only really interested in what a test file looks like at this point. The actual tests themselves are about to change as we re-implement the requestReducer to handle our array of named requests, as per the previous video.

I'll finish up with my favourite saying:

If you don't have time for tests, you must have plenty of time for problems

:)

Gotchas

Specifically to this boilerplate, I've noticed a bug when trying to run the Jest filter facility in conjunction with the automated tests run by npm start -s. The filter input tends to glitch out. My solution to this is to simply run a seperate console tab with yarn test:watch running completely separate to the server.

I also wrote a blog post on adding Jest to this boilerplate which you may find interesting if you continue with Jest.

Code For This Course

Get the code for this course.

Code For This Video

Get the code for this video.

Episodes