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.