Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get karma-coverage (istanbul) to check coverage of ALL source files?

The code structure

I have an app directory structure like

scripts/sequoia/                              
├── GraphToolbar.js                     
├── nodes                                     
│   ├── activityNode.js                       
│   └── annotationNode.js                     
├── OverviewCanvasControl.js                  
└── settings                                  
    ├── GraphControlSettingsFactory.js        
    └── SnapContextFactory.js                 

My test directory current looks thus

test/spec/                                        
├── GraphToolbarSpec.js                           
├── settings                                      
│   ├── graphControlSettingsFactorySpec.js        
│   └── snapContextFactorySpec.js                 
└── test-main.js

Note that I only have GraphToolbar and the settings/ files covered so far; there are no tests yet for OverviewCanvasControl.js or the nodes/ files.

The karma config

In my karma.conf.js (coverage refers to karma-coverage):

preprocessors: {                     
  'scripts/sequoia/**/*.js': ['coverage']
},                                   
reporters: ['progress','coverage'],

The problem

When I run karma, the coverage preprocessor & reporter run, but it only checks the files that already have specs written. I want to be reporting 0% coverage for OverviewCanvasControl.js and the nodes/ files that have no coverage. When a new file is created & karma is run, I want it to catch that that file has no Spec yet.

How can I get Karma to check all matching source files for coverage, not just those with specs already created?

like image 228
Stop Slandering Monica Cellio Avatar asked May 22 '14 17:05

Stop Slandering Monica Cellio


3 Answers

After searching for I while I found that it is quite easy. Add this to your karma.conf.js:

coverageReporter: {
    includeAllSources: true,
    reporters: [
        ...
    ]
}

BR Chris

like image 134
cschuff Avatar answered Nov 17 '22 15:11

cschuff


I were struggling with this and I found a pretty nice solution.

Before executing tests, I execute a task that will walk through your js files and require them on a single spec file. This will make files to be instrumented and code coverage will be generated correctly. Since Istanbul only instruments files that are required by the specs. Showing the coverage from your specs and not from your code. This will fix this issue.

It was inspired on the sequoia mcdowell response and I hope it help others.

http://shared-mind.tumblr.com/post/89641439478/istanbul-code-coverage-force-instrumentation-of-all-file

like image 40
prnjanuario Avatar answered Nov 17 '22 16:11

prnjanuario


Solution I came up with: walk source tree & check that a spec file exists for each source JS file. This assumes that each source file has a corresponding Spec.js file (residing in a corresponding directory structure).

  • app/scripts/moduleFoo.jstest/spec/moduleFooSpec.js
  • app/scripts/ns1/Utils/foo_bar.jstest/spec/ns1/Utils/foo_barSpec.js

Task relies on fs-tools npm module.

var fsTools = require('fs-tools');
//... module.exports = function(grunt) { ... etc. (gruntfile setup)

  grunt.registerTask('checkspecs', 'ensure that all js files have Specs', function(){
    var done = this.async();
    var srcPath = './'+cfg.app+'/scripts/'; //Where are your scripts?
    var testPath = './test/spec/';          //Where are your specs?
    var missingSpecs = [];
    fsTools.walk(srcPath, '.js$', function(path,stats,callback){
      var specPath = testPath + path.substring(path.indexOf('ptc')+4);
      //strip .js, add Spec.js
      specPath = specPath.split('').slice(0,-3).join('') + 'Spec.js';
      if(!grunt.file.exists(specPath)){
        missingSpecs.push(path);
      }
      callback();
    }, function (err){
      if(err){
        grunt.log.error(err);
        done(false);
      }
      if(missingSpecs.length > 0){
        grunt.log.warn('`Spec.js` files are missing for the following files!!');
        missingSpecs.forEach(function(path){
          grunt.log.warn(path);
        });
      }else{
        grunt.log.ok('Spec files present for all source files');
      }
      done(!err);                   //fail only if fsTools.walk throws
      //done(!missingSpecs.length); //fail if any specs are "missing"
    });
  });

Why don't you package this as a grunt task and publish to NPM?

Mostly because it relies a lot on the specific paths & naming conventions in your project. It doesn't exclude directories/files yet (this may be necessary) & if you don't do *Spec.js it won't work. Imo it's probably easier to take this snippet & customize it than to externalize everything & make it a configurable task. Might change this later. 😺

like image 42
Stop Slandering Monica Cellio Avatar answered Nov 17 '22 16:11

Stop Slandering Monica Cellio