Search code examples
javascriptrequirejskarma-runnerkarma-coverage

Karma Coverage + RequireJS: Misleading coverage reports


Today I've integrated Karma Coverage to my existing RequireJS application. I added the karma-requirejs plugin and I was able to successfully get the coverage reports.

Initially the report was very good, almost 100% coverage. When I carefully analyzed the results I noticed a lot of missing files from my "src" folder which led to this extremely good report.

It turns out that the coverage is just applying the analysis for the "src" files that have a corresponding spec (because I use require('someFileFromSrcFolder') inside that spec).

Question: Is there a way for the coverage to analyze all the files from "src" folder?

Karma-conf.js

module.exports = function (config) {
    config.set({
        basePath: '../',
        autoWatch: true,
        singleRun: false,
        frameworks: ['jasmine', 'requirejs'],
        browsers: ['PhantomJS', 'Chrome'],
        logLevel: config.LOG_ERROR,
        files: [
            {pattern: 'vendor/**/*.js', included: false},
            {pattern: 'vendor/**/*.html', included: false},
            {pattern: 'src/**/*.js', included: false},
            {pattern: 'src/**/*.html', included: false},
            {pattern: 'tests/mock/**/*.js', included: false},
            {pattern: 'tests/**/*Specs.js', included: false},

            'tests/test-require.js'
        ],

        // list of files to exclude
        exclude: [
            'src/app-require.js'
        ],

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

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

Test-require.js

var allTestFiles = [];
var TEST_REGEXP = /Specs\.js$/;

Object.keys(window.__karma__.files).forEach(function (file) {
    if (TEST_REGEXP.test(file)) {
        allTestFiles.push(file);
    } 
});

require.config({

    baseUrl: '/base/',

    paths: {
       ...
    },

    deps: allTestFiles,

    callback: window.__karma__.start(),

waitSeconds: 20
});

Solution

  • Ok,

    After trying for a little bit I was able to come to a solution that seems to fix the problem. I'm still not sure if this is the best solution but I will post here what I did so that I can gather your feedbacks.

    Basically, I had to change the load mechanism in test-require.js to include all my packages by default. The updated test-require.js should look like follows:

    Updated Test-require.js

    var allTestFiles = [];
    var modules = [];
    var TEST_REGEXP = /Specs\.js$/;
    var SRC_REGEXP = /src\//;
    var JS_REGEXP = /\.js$/;
    
    /**
    * This function converts a given js path to requirejs module
    */
    var jsToModule = function (path) {
        return path.replace(/^\/base\//, '').replace(/\.js$/, '');
    };
    
    Object.keys(window.__karma__.files).forEach(function (file) {
        if (TEST_REGEXP.test(file)) {
            allTestFiles.push(file);
        } else if (SRC_REGEXP.test(file) && JS_REGEXP.test(file)) {
            modules.push(jsToModule(file));
        }
    });
    
    var startTest = function () {
        //loading all the existing requirejs src modules before
        //triggering the karma test
        require(modules, function () { 
            window.__karma__.start();
        });
    };
    
    require.config({
    
        baseUrl: '/base/',
    
        paths: {
           ....
        },
    
        // dynamically load all test files
        deps: allTestFiles,
    
        callback: startTest,
    
        waitSeconds: 20
    });
    

    Now, when I run test tests, the coverage includes all the src modules and I can finally get a consistent and accurate reports.