Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Karma tests: measure coverage for untested code

I have successfully set up testing with Karma and Webpack for my sandbox project written in Typescript. The code coverage metrics are collected by Istanbul Instrumenter Loader. What bothers me is that I get the coverage reported only for the modules that are being imported in the tests, so the reported coverage of 100% is in fact a dirty lie.

Looking for a solution, I have found a passage in Istanbul Instrumenter Loader's readme:

To create a code coverage report for all components (even for those for which you have no tests yet) you have to require all the 1) sources and 2) tests.

test/index.js

// requires all tests in `project/test/src/components/**/index.js`
const tests = require.context('./src/components/', true, /index\.js$/);

tests.keys().forEach(tests);

// requires all components in `project/src/components/**/index.js`
const components = require.context('../src/components/', true, /index\.js$/);

components.keys().forEach(components);

If I understand correctly, this snippet walks over all index files in source dir and imports everything from them. My question is: how to correctly translate this snippet to Typescript? Or is there a better solution that does not require the import * from * workaround?

Edit

I've found this question: Typescript 1.8 modules: import all files from folder. Does this mean that I need an index.ts file where I have to import each module? This would mean that each time I introduce a new module file, I have to manually add its import to index.ts? There must be a better way.

Edit 2

I'm also open to other tools that can generate coverage report for the whole code base, the only condition them being able to cope with the Typescript + Webpack + Karma + Mocha stack. I have tried nyc, but couldn't manage to get any code coverage at all.

Edit 3

Here's the index.js from above translated to Typescript:

declare const require: any;

const ctx = require.context('../src', true, /\.ts$/);
ctx.keys().map(ctx);

Edit 4

There's a karma plugin now called karma-sabarivka-reporter that corrects the coverage statistics. Check out the accepted answer for details.

like image 236
hoefling Avatar asked Aug 10 '18 16:08

hoefling


2 Answers

IMPORTANT:

This answer will not solve the above problem, it's fundamentally wrong. See comments.


NYC supports coverage for untested code with --all flag. Assuming your test command in package.json is

"test": "karma start karma.conf.js",

You can test coverage after npm install -D nyc ts-node, you can add the following command and run it. This command expects the source code to check for coverage to be in src directory.

"coverage": "nyc --all --include src --extension .ts --require ts-node/register npm test",
  • --all flag is used to check all files for coverage.
  • --extension .ts is for checking all TypeScript files, you can add more extension like --extension .ts --extension .tsx.
  • --include src is for the directory to check for coverage.
  • -- require ts-node/register is to teach NYC to understand TypeScript.

After that you should see all .ts files being included.

Note: Using ts-node/register may cause issues with line numbers on reports. To solve this you will probably need to register source map support as well..

like image 164
dereli Avatar answered Nov 12 '22 02:11

dereli


For projects tested using Karma + Istanbul as coverage reporter – I've just created karma plugin, which adds all the files in the project to coverage statistic - https://github.com/kopach/karma-sabarivka-reporter.

To use it -> install npm install --save-dev karma-sabarivka-reporter

And update karma.conf.js like this:

reporters: [
  // ...
  'sabarivka'
  // 'coverage-istanbul' or 'coverage' (reporters order is important for 'coverage' reporter)
  // ...
],
coverageReporter: {
  include: [
      // Specify include pattern(s) first
      'src/**/*.(ts|js)',
      // Then specify "do not touch" patterns (note `!` sign on the beginning of each statement)
      '!src/main.(ts|js)',
      '!src/**/*.spec.(ts|js)',
      '!src/**/*.module.(ts|js)',
      '!src/**/environment*.(ts|js)'
  ]
},
like image 20
Ihor Avatar answered Nov 12 '22 03:11

Ihor