Unit testing code coverage

In the first part of this series, I discussed when and how Apigee custom code can be unit tested.

In this article I want to talk about how to measure test coverage to ensure our tests are covering a high percentage of our code.

We can start with a slightly refactored folder structure of the code we wrote in the first part:

- src/
  |
  -  LogToLoggly.js
- test/
  |
  -  LogToLogglyTest.js

Refer to the first part for the source codes for those files.

In order to implement code coverage, we can use a tool called Istanbul. It computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests.

We will hook Istanbul into our workflow using gulp which is my favourite build system.

We start by installing all the dependencies:

npm install gulp -g
npm install gulp --save-dev
npm install gulp-istanbul --save-dev
npm install gulp-mocha --save-dev
npm install sinon --save-dev
npm install expect.js --save-dev

Create a new file on the root folder called "gulpfile.js":

var gulp = require('gulp');
var mocha = require('gulp-mocha');
var istanbul = require('gulp-istanbul');


gulp.task('test', function (cb) {
  gulp.src(['./src/*.js'])
    .pipe(istanbul())
    .pipe(istanbul.hookRequire()) 
    .on('finish', function () {
      gulp.src(['./test/*.js'])
        .pipe(mocha())
	.pipe(istanbul.writeReports())
	.pipe(istanbul.enforceThresholds({ thresholds: { global: 90 } }))
	.on('end', cb);
    });
});

You can now run this gulp task by:

$ gulp test

[14:28:22] Using gulpfile ~/..../gulpfile.js
[14:28:22] Starting 'test'...

  feature: logging to Loggly
    ✓ should log success responses correctly
    ✓ should log failure responses correctly

  2 passing (49ms)

---------------------|-----------|-----------|-----------|-----------|
File                 |   % Stmts |% Branches |   % Funcs |   % Lines |
---------------------|-----------|-----------|-----------|-----------|
   src/              |       100 |       100 |       100 |       100 |
      LogToLoggly.js |       100 |       100 |       100 |       100 |
---------------------|-----------|-----------|-----------|-----------|
All files            |       100 |       100 |       100 |       100 |
---------------------|-----------|-----------|-----------|-----------|

============= Coverage summary =============
Statements   : 100% ( 7/7 )
Branches     : 100% ( 2/2 )
Functions    : 100% ( 0/0 )
Lines        : 100% ( 7/7 )
============================================
[14:28:22] Finished 'test' after 264 ms

The following line in gulpfile will fail the tests if coverage is below 90% - which is very handy for CI:

.pipe(istanbul.enforceThresholds({ thresholds: { global: 90 } }))

If you fall below the 90% mark, you will get the following output from gulp test:

$ gulp test

[15:52:14] Using gulpfile ~/..../gulpfile.js
[15:52:14] Starting 'test'...

  feature: logging to Loggly
    ✓ should log failure responses correctly

  1 passing (31ms)

---------------------|-----------|-----------|-----------|-----------|
File                 |   % Stmts |% Branches |   % Funcs |   % Lines |
---------------------|-----------|-----------|-----------|-----------|
   src/              |       100 |        50 |       100 |       100 |
      LogToLoggly.js |       100 |        50 |       100 |       100 |
---------------------|-----------|-----------|-----------|-----------|
All files            |       100 |        50 |       100 |       100 |
---------------------|-----------|-----------|-----------|-----------|

============= Coverage summary =============
Statements   : 100% ( 7/7 )
Branches     : 50% ( 1/2 )
Functions    : 100% ( 0/0 )
Lines        : 100% ( 7/7 )
=============================================
            ^
Error: Coverage failed

Once you execute the gulp task, apart from the command line dump of coverage percentages, you will get a folder created, called coverage, which contains HTML coverage reports. Open index.html with your browser.

460-screen-shot-2015-05-19-at-162916.png

And here is an example of an HTML report with missing coverage:

461-screen-shot-2015-05-19-at-163147.png

Comments
Not applicable

Nice example and great use of Gulp

munimanjunathka
New Member

After installing all the above said npm modules I ran the test script directly

.\node_modules\.bin\nyc --all --report-dir=.\coverage --reporter=text .\node_modules\.bin\mocha "test\**\*.js"

which gave me code coverage after mocha script execution. There seems to be problem with gulp-mocha version

Version history
Last update:
‎05-19-2015 08:32 AM
Updated by: