Search code examples
typescriptkarma-jasminecoberturakarma-coverage

Get Cobertura coverage from an angular5 app in typescript


I am currently working on a project where we want to have some code coverage for our unit tests. The tests are running fine but I have some trouble getting the right coverage.

Our CiCd runs in VSTS and it requests an export of the code coverage in Cobertura or JaCoCo in order to publish the result.

So our app is an Angular 5 application written fully in TypeScript with the specs files embedded with each component / module / ...

Our tests are running with karma, jasmine, with chrome and my karma.conf.js looks like this right now:

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular/cli/plugins/karma'),
      require('karma-junit-reporter'),
      require('karma-remap-coverage'),
      require('karma-coverage'),
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    files: [
      { pattern: 'src/**/*.ts' }
    ],
    preprocessors: {
      './src/**/*.ts': ['coverage']
    },
    coverageIstanbulReporter: {
      reports: [ 'cobertura' ],
      fixWebpackSourcePaths: true
    },
    coverageReporter: {
      type: 'in-memory'
    },
    remapOptions: {
      basePath: './src'
    },
    remapIstanbulReporter: {
      reports: {
        html: 'coverage',
        cobertura: './coverage/cobertura.xml',
      }
    },
    remapCoverageReporter: {
      'text-summary': null, // to show summary in console
      html: './coverage/html',
      cobertura: './coverage/cobertura.xml'
    },
    angularCli: {
      config: './angular-cli.json',
      environment: 'dev',
      codeCoverage: true
    },
    reporters: ['progress', 'junit', 'coverage', 'remap-coverage'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    sourceMaps: true
  });
};

There is a configuration for junit as VSTS can export the result in junit too but I don't think it's the cause of my problem right now. Also the conf file might have some configurations that does nothing but are there because of all the tests I've done yesterday to get this to work.

My concerns are that the code coverage is done on nothing as the console output it at the end of the run:

=============================== Coverage summary ===============================
Statements   : 100% ( 0/0 )
Branches     : 100% ( 0/0 )
Functions    : 100% ( 0/0 )
Lines        : 100% ( 0/0 )
================================================================================

But I'm sure my tests are fine : Chrome 66.0.3359 (Mac OS X 10.12.6): Executed 264 of 291 (skipped 27) SUCCESS (9.286 secs / 0 secs)

Also at the beginning of the run I have a lot of errors showing :

04 05 2018 10:51:51.473:ERROR [preprocessor.coverage]: Line 1: Unexpected token
  at /Users/user/Documents/work/project/src/app/settings/settings.component.spec.ts
Failed to parse file: /Users/user/Documents/work/project/src/app/settings/settings.component.ts

Maybe it can come from here? But i don't know what these errors are and why I am getting them.

Overall, I found it very difficult to find a great tutorial on this on the web, having lots of different libs calling each other (karma / coverage / istanbul / karma-typescript / ....) and their doc being quite light.

What am I doing wrong ? How can I fix this ?


Solution

  • Overall, I found it very difficult to find a great tutorial on this on the web, having lots of different libs calling each other (karma / coverage / istanbul / karma-typescript / ....) and their doc being quite light.

    I felt the same way. (And many times I've stumbled across this very StackOverflow question when searching for an answer.)

    Fortunately, I was finally able to get a cobertura report from karma today. Here's how to set it up:

    In my package.json:

    {
      "devDependencies": {
        "jasmine-core": "5.1.1",
        "jasmine-reporters": "2.5.2",
        "jasmine-spec-reporter": "7.0.0",
        "karma": "6.4.2",
        "karma-chrome-launcher": "3.2.0",
        "karma-cli": "2.0.0",
        "karma-coverage": "2.2.1",
        "karma-jasmine": "5.1.0",
        "karma-jasmine-html-reporter": "2.1.0",
        "karma-junit-reporter": "2.0.1",
      },
      // other settings
    }
    

    In my karma.conf:

    module.exports = function (config) {
      config.set({
        basePath: '',
        frameworks: ['jasmine', '@angular-devkit/build-angular'],
        plugins: [
          require('karma-jasmine'),
          require('karma-jasmine-html-reporter'),
          require('karma-coverage'),
          require('@angular-devkit/build-angular/plugins/karma'),
        ],
        coverageReporter: {
          dir: require('path').join(__dirname, 'coverage'),
          reporters: [
            { type: 'html', subdir: 'report-html' },
            { type: 'cobertura', subdir: '.', file: 'cobertura-coverage.xml' },
            { type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt' },
          ],
          fixWebpackSourcePaths: true
        },
        reporters: ['progress', 'kjhtml', 'junit', 'coverage'],
        // other settings
    }
    

    Note that there is no mention of istanbul. It's still used under the hood, but the karma-coverage-istanbul-reporter project is deprecated. Instead, just use karma-coverage.

    The key thing is this part: { type: 'cobertura', subdir: '.', file: 'cobertura-coverage.xml' }

    Unfortunately, as I was figuring this all out, I also found out that the entire karma project is deprecated. So, soon we'll have to start this journey all over again.


    The above should be useful to anyone who finds this searching for "cobertura karma" or similar, but the OP's real problem is this having completely invalid Typescript: Line 1: Unexpected token at settings.component.spec.ts

    Regardless, I hope the above is helpful for those (like me) who stumble upon this question trying to get Cobertura to work.