From 0 to 100% Coverage Real Quick
My experience unit testing Premiere
I recently posted about Premiere, a Javascript library I've published to facilitate consuming RESTful APIs and one of my goals to make this library reliable was to achieve 100% test coverage or at least close to that.
To do so, my first choice was to choose the how to do it; so I started reading about the popular Mocha/Chai/Sinon + Istanbul for test coverage. Although I got to setup the basic testing environment and script, my experience was very painful; using Typescript made testing even more difficult than it should be.
If you are used to Karma, Jasmine, Mocha/Chai/Sinon and happy with them, that’s good too. This post is about the experience I've had so far with these technologies.
After a lot of hustle, time spent, and packages imported, the test watcher
and coverage
were still not working for me. To do simple tests I had to import stuff in my code from many libraries, some from chai
, some other from sinon
, others from sinon-chai
and it all looked very difficult and confusing; plus, I was working with Typescript and needed all the typings. By the end I was very frustrated it all turned out to deviate me from the main focus, which was to write tests, not to do configurations.
Doing some research I found out about Jest, a testing framework created and used by Facebook. At first I thought it was designed to be used with React projects only, but going through the Jest Homepage I started to notice how powerful and easy to setup it was. Even better, there is a nice package for handling Typescript without a sweat.
Setting up Jest was easy like a breeze, it has a nice watcher and the test coverage works out of the box. The whole flow felt very smooth, having everything in on place made it a lot easier, the well documented api was very helpful too.
Once everything was in place, it was just a matter of going through each functionality and making sure everything was covered to get the so desired 100% coverage ❤. The basic functions, describe
, it
and expect
were enough in most of the cases and the support to Promise
took care of the rest. To help isolating each test, creating mocks with jest.fn()
also was of great help.
Let's see some code, so this doesn't sound so much as free marketing for Facebook. The following code is written in Typescript and refers to Premiere's Cache class.
To get started, let's import the main class. I followed the pattern of placing the .spec.ts
in the same folder as the "original" file.
import Cache from './Cache';
Now let's set our describe
block and prepare some variables for our tests, so we make our lives easier. Notice that we're using variables with type any
, so we don't need to import more stuff other than Cache, with the goal of trying to make our spec
more isolated.
describe('Cache', () => {
let cache: Cache;
let model: any;
let list: any[];
let promise: any = 'promise instance';
Now, before each test we'll initialize our variables.
beforeEach(() => {
cache = new Cache(null);
model = {key: jest.fn().mockReturnValue('id')};
list = [model];
});
To get a hold of how it works, let's look at a couple tests.
it('should set api on construct', () => {
cache = new Cache('api' as any);
expect(cache.api).toBe('api');
});it('should resolve key from object', () => {
expect(Cache.resolveKey(model)).toBe('id');
});it('should set list', () => {
cache.setList('list', list);
expect(cache.lists['list']).toBe(list);
});
If you wish to see the entire file, please refer to https://github.com/pedsmoreira/premiere/blob/master/lib/premiere/Cache.spec.ts
The configuration
The Jest configuration is dead simple. Just added these parts to package.json.
Scripts:
“test”: “jest — coverage — no-cache ${1}”,
“test-watch”: “jest ${1} — watch”,
Dev Dependencies:
"@types/jest": "^16.0.2",
"jest": "^18.0.0",
"ts-jest": "^18.0.0",
And finally the "jest" block.
This part is only necessary because the project uses Typescript. Don't get scared, this is mostly boilerplate that are nicely documented by ts-jest.
"jest": {
"moduleFileExtensions": [
"ts",
"js"
],
"transform": {
"\\.(ts)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "lib/.*\\.spec.(ts|js)$",
"testResultsProcessor": "<rootDir>/node_modules/ts-jest/coverageprocessor.js",
"globals": {
"__TS_CONFIG__": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node"
}
}
}
The full package.json is available at https://github.com/pedsmoreira/premiere/blob/master/package.json
So if you have a chance, with or without, give Jest a try, you may surprise yourself. It’s very nice to feel that things “just work” \o/
I hope you enjoy :)
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!