How to generate LCOV report based on Jasmine's SpecRunner.html?

SBel picture SBel · May 5, 2015 · Viewed 8.9k times · Source

We are using Jasmine for our JavaScript unit tests. We have a SpecRunner.html file to run the tests. Does there exist a tool to which I can pass the path to SpecRunner.html and the path to the directory of JavaScript (not the specs) files and it would generate a LCOV report. For example, something like this:

phantomjs jasmine_lcov.js SpecRunner.html WebContent/js

Answer

johnmcase picture johnmcase · May 22, 2015

I agree with @zaabalonso that Karma is the correct choice. Since you want LCOV reports, you'll also need the karma-coverage plugin and presuming you want to run headless in CI you'll probably want the karma-phantomjs-launcher. Running through Grunt is optional as you can always run karma directly from the command line with karma-cli (npm install -g karma-cli).

A basic setup (with requireJS) looks something like this:

package.json

{
  "private": "true",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-jasmine-node": "^0.3.1",
    "grunt-karma": "^0.10.1",
    "jasmine-core": "^2.3.4",
    "karma": "^0.12.32",
    "karma-coverage": "^0.3.1",
    "karma-jasmine": "^0.3.5",
    "karma-phantomjs-launcher": "^0.1.4",
    "karma-requirejs": "^0.2.2",
    "requirejs": "^2.1.17"
  }
}

karma.conf.js (Notice the preprocessors and coverageReporter sections

module.exports = function(config) {
  config.set({
  basePath: '.',
  frameworks: ['jasmine', 'requirejs'],
  files: [{
        pattern: 'src/**/*.js',
        included: false
      }, {
        pattern: 'spec/**/*.js',
        included: false
      },
      "test-main.js"],

  preprocessors: {
    'src/**/*.js': ['coverage']
  },

  reporters: ['progress', 'coverage'],

  coverageReporter: {
    // specify a common output directory
    dir: 'build/reports/coverage',
    reporters: [
      { type: 'lcov', subdir: 'report-lcov' },
      { type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt' }
    ]
  },

  browsers: ['PhantomJS']
  });
};

test-main.js

var allTestFiles = [];
var TEST_REGEXP = /^\/base\/spec\/\S*(spec|test)\.js$/i;

var pathToModule = function (path) {
    return path.replace(/^\/base\//, '').replace(/\.js$/, '');
};

Object.keys(window.__karma__.files).forEach(function (file) {
    if (TEST_REGEXP.test(file)) {
        // Normalize paths to RequireJS module names.
        allTestFiles.push(pathToModule(file));
    }
});

require.config({
    // Karma serves files under /base, which is the basePath from your config file
    baseUrl: '/base/',
    enforceDefine: true,
    xhtml: false,
    waitSeconds: 30,

    // dynamically load all test files
    deps: allTestFiles,
    callback: window.__karma__.start
});

Gruntfile.js (Optional if you want to use Grunt)

module.exports = function(grunt) {
  grunt.initConfig({
    karma: {
      unit: {
        configFile: 'karma.conf.js',
        options: {
          singleRun: true
        }
      }
    }
  });
  grunt.loadNpmTasks('grunt-karma');
  grunt.registerTask('default', ['karma:unit']);
};

You can run the tests command line with karma start. That will launch the karma server and run the tests once. It will keep the server up and will re-run the tests anytime you modify your source or test sources. If you want to run the test only once (in CI perhaps) you simply run karma start --single-run.