Run all your JavaScript Jasmine tests on every commit

Published: 2013-04-07 by Lars  pipeline

I've previously described how to run your QUnit tests and produce a coverage report on every commit. This works great if you happen to have chosen QUnit as your unit testing framework.

Jasmine is another popular JavaScript unit testing framework. Here I will show how you can get the same automated feedback from your Jasmine tests using Grunt. Refer to the full sample project on GitHub: github.com/larsthorup/jsdevenv-jasmine.

Assume that we have the following very simple Jasmine test in src/js/addition.test.js:

/*global describe it expect */
describe('addition', function () {
    'use strict';

    it('should return 4 when adding 2 and 2', function () {
        expect(2 + 2).toBe(4);
    });
});

To run this test from the command-line, we need to install the Jasmine-plugin for Grunt. Add this line to package.json:

        "grunt-contrib-jasmine": "0.4.1",

And install it with npm install. You can then configure the plugin in Gruntfile.js:

    grunt.loadNpmTasks('grunt-contrib-jasmine');
    gruntConfig.jasmine = {
        src: {
            src: [
                'src/js/**/*.js',
                '!src/js/**/*.test.js'
            ],
            options: {
                specs: 'src/js/**/*.test.js',
                junit: {
                    path: 'output/testresults'
                }
            }
        }
    };
    grunt.registerTask('test', 'jasmine:src');

You can now run your Jasmine tests from the command line with grunt test. If you try to make the test fail, it will produce output like this:

$ grunt test
Running "jasmine:src" (jasmine) task
Testing jasmine specs via phantom
x.........
addition:: should return 4 when adding 2 and 2: failed
  Expected 4 to be 5. (1)
10 specs in 0.003s.
>> 1 failures

Notice that the Jasmine plugin supports JUnit-formatted test results out of the box, so you can configure your CI-server to display test results and trend lines from the files that Jasmine produces in output/testresults.

To produce a coverage report we can use the JavaScript code coverage tool Istanbul that has a plugin for the Jasmine-plugin for Grunt. To install it add this line to package.json:

        "grunt-template-jasmine-istanbul": "0.2.0"

and run npm install. You can then configure the plugin in Gruntfile.js:

    gruntConfig.jasmine.istanbul= {
        src: gruntConfig.jasmine.src.src,
        options: {
            specs: gruntConfig.jasmine.src.options.specs,
            template: require('grunt-template-jasmine-istanbul'),
            templateOptions: {
                coverage: 'output/coverage/coverage.json',
                report: [
                    {type: 'html', options: {dir: 'output/coverage'}},
                    {type: 'cobertura', options: {dir: 'output/coverage/cobertura'}},
                    {type: 'text-summary'}
                ]
            }
        }
    };
    grunt.registerTask('coverage', 'jasmine:istanbul');

You can now run your Jasmine tests with coverage analysis with the command grunt coverage. It will produce output like this:

$ grunt coverage
Running "jasmine:istanbul" (jasmine) task
Testing jasmine specs via phantom
..........
=============================== Coverage summary ===============================
Statements   : 100% ( 33/33 )
Branches     : 89.29% ( 25/28 )
Functions    : 100% ( 4/4 )
Lines        : 100% ( 30/30 )
================================================================================

10 specs in 0.062s.
>> 0 failures

Done, without errors.

Istanbul will also product html-output that can be browsed from output/coverage/index.html, and will look like this:

Some CI-servers, like Jenkins, can display coverage information and trend-lines, if the coverage information is in Cobertura-format. We also configured Istanbul to output in Cobertura-format so we can point our CI-server at the files in output/coverage/cobertura.

This post is part of a series on Continuous Integration for front-end JavaScript, read the other posts in the series:

Discuss on Twitter