5
votes

I had some difficulties running Istanbul code coverage tool with Angular.js + Jasmine. I'm coding in Coffeescript, but since Instanbul doesn't support it yet, source is converted to JS on every save.

Basically, I don't see the relation between tests and tested code here, because files with no unit tests at all still get 66% coverage, which, well... doesn't make sense at all.

As I've mentioned in the title, I'm using Karma as a test runner but command-line produces the same result.

Example Angular.js controller (compiled .coffee):

'use strict';
angular.module('app.controllers').controller('HelpIndexCtrl', [
  '$scope', function($scope) {
    return $scope.foo = 'bar';
  }
]);

and the unit test:

'use strict'
describe "controllers", ->
  beforeEach angular.mock.module "app.controllers"
  scope = rootScope = {}
  describe "HelpIndexCtrl", -> inject ($controller)->
    ctrl = $controller 'HelpIndexCtrl', $scope:scope
    it 'should have working scope', ->
      expect(scope.foo).toBe 'bar'

General coverage results

Example controller

Example controller

1
The 66% statement coverage on files without unit tests is from some of the statements executing when Karma loads the files. The controller declarations angular.module().controller() and the 'use strict' statements are both being evaluated during the loading process.Noah Freitas
Thanks for your comment. I'm aware of that. The point is - why the rest of the code, ie. unit tests are not evaluated at all? I've ran unit tests with Karma + Istanbul, but result is the same.Rafal Pastuszak
What does your karma config file look like?Noah Freitas
@NoahFreitas Sorry for such a late response. The reason it didn't work was a bug in unit tests which caused loading Angular.js mocks twice and disabling inject methods in several, seemingly random, cases. I've also converted all .coffee files to js on the fly and disabled coffeescipt precompilation in Karma to make sure, there are no issues with compilation. I think that it's a good thing to do since you're using same precompilation settings in unit tests and actual code. I'll post an answer with working karma.conf.js as soon as I get back to the office.Rafal Pastuszak
I'm sooo sorry, just posted answer with a solution that worked perfectly in my case. Hopefully you'll find it useful despite of the delay:)Rafal Pastuszak

1 Answers

3
votes

Here's the solution that worked perfectly in my case and powered several medium and large projects (I'm using [email protected]):

It turned out that it's much more convenient for me to convert .coffee files using grunt and then pass .js files to karma coverage processor:

Karma configuration

  module.exports = function (karma) {
    karma.set({
      basePath: '../',
      frameworks: ['jasmine'],
      files: [

        // -------- START: IMPORTS ----------


        "vendor/angular-ui-utils/modules/ie-shiv/ie-shiv.js",
        "vendor/jquery/jquery.js",
        "vendor/es5-shim/es5-shim.js",
        "vendor/lodash/lodash.js",
        "vendor/angular/angular.js",

        // and so on for the next 80 lines...



        // -------- END: IMPORTS ----------


        'vendor/angular-mocks/angular-mocks.js',
        "vendor/sinonjs/sinon.js",
        'vendor/angular-*/angular-*.js',



        'public/js/templates.js',

        'test/js/**/*.js',


        //////////////////
        // Custom Mocks //
        //////////////////
        'test/js-unit/**/*.mock.js',

        //////////////////
        // CoffeeScript //
        //////////////////
        'test/js-unit/**/*.spec.js'
      ],
      reporters: ['progress', 'coverage', 'junit'],

      plugins: [
        'karma-jasmine',
        'karma-script-launcher',
        'karma-phantomjs-launcher',
        'karma-junit-reporter',
        'karma-coverage',
        'karma-coffee-preprocessor',
        'karma-growl-reporter'
      ],


      junitReporter: {
        outputFile: 'test-results.xml'
      },

      // web server port
      // CLI --port 3334
      port: 3334,

      // cli runner port
      // CLI --runner-port 9100
      runnerPort: 9100,

      // enable / disable colors in the output (reporters and logs)
      // CLI --colors --no-colors
      colors      : true,
      logLevel    : karma.LOG_DISABLE,
      autoWatch   : true,
      loggers     : [],
      browsers    : ['PhantomJS'],

      // If browser does not capture in given timeout [ms], kill it
      // CLI --capture-timeout 5000
      captureTimeout: 5000,

      // Auto run tests on start (when browsers are captured) and exit
      // CLI --single-run --no-single-run
      singleRun: true,

      // report which specs are slower than 500ms
      // CLI --report-slower-than 500
      reportSlowerThan: 500,

      coverageReporter : {
        type: 'html',
        dir: 'test/coverage/'
      },

      preprocessors: {
        'test/js/**/*.js': 'coverage'
      }
    });

  }

GruntFile.json snippet:

coffee:
  compile:
    files:
      'public/js/app.js' : ['app/**/*.coffee']
    options:
      sourceMap: yes
      join: yes
      bare: yes
  compileForTests:
    options:
      bare: yes
    expand: yes
    flatten: no
    cwd: 'app/'
    src: ['**/*.coffee']
    dest: 'test/js/'
    ext: '.js'
  compileTests:

Important

Note that subsequent minor versions of karma require different configuration settings. This config won't work on [email protected]. However, the differences in config structure are mostly aesthetic (eg. config method refactored to set, etc..).