8

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.

Community
  • 1
  • 1
hoefling
  • 59,418
  • 12
  • 147
  • 194
  • maybe just add test cases for all of your files and just do describe in those you would not want to test. what you are trying to achieve sounds a bit anti-pattern anyway, in sense you should only care about your test results. – Jimi Pajala Aug 13 '18 at 13:32
  • I don't think that achieving true code coverage counts as an antipattern, here's what [React devs](https://coveralls.io/github/facebook/react) code coverage looks like, with [uncovered source files included](https://coveralls.io/builds/18457263/source?filename=packages/shared/ReactSharedInternals.js). Thing brings me actually to the idea of trying to replace Karma with [Jest](https://jestjs.io/). – hoefling Aug 13 '18 at 15:52
  • I can personally strongly recommend Jest. It's very intuitive to use and it's basically `no configuration needed` setup. I have also used Jest to collect testing coverage of React translation -component of mine which worked great. You might also want to check out Airbnb/Enzyme which exposes some easier to use testing functions. – Jimi Pajala Aug 14 '18 at 05:53
  • The pattern is to write each component spec test and based on the karma config file, webpack should pick up on all tests under /src as well as /tests. I tried your repo and it works as intended. – Arielle Nguyen Aug 19 '18 at 08:44

2 Answers2

3

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..

Community
  • 1
  • 1
dereli
  • 1,814
  • 15
  • 23
  • This already looks more promising than everything I've seen so far; however, `nyc` doesn't pick up all source files - for example, `src/_modules/Utils.ts` is missing. Do you have any idea how to include all source files with `nyc`? – hoefling Aug 19 '18 at 11:05
  • Oops. The reason NYC doesn't include all files is, it doesn't understand TypeScript syntax. Updating the answer to fix that issue. – dereli Aug 19 '18 at 11:38
  • Getting better - all files are picked up now, but it looks like the coverage is not collected: all files have zero code lines covered. At least `Utils.ts` should have some covered lines... When I leave `--include src` out, I see that `karma.conf.js` has 100% line coverage, which means something is collected. – hoefling Aug 19 '18 at 12:21
  • I have included `--require source-map-support/register` and tried out some additional options, but with no awail - I've pushed the latest changes in `package.json` to master branch. – hoefling Aug 19 '18 at 12:21
  • For source map support to consume, ts-node needs to create source maps correctly. Previously I had the best results with inline source maps. I will try to check out and put together an example – dereli Aug 19 '18 at 12:31
  • Taking a step back, I found out an important mistake. It's not possible to user NYC to check coverage with Karma. Karma runs tests in Browser which is a different process. Your best bet is changing Karma with Mocha (and JSDOM etc if needed) or trying some other coverage plugins for Karma. – dereli Aug 19 '18 at 13:52
  • That's a pity! However, thank you for your efforts - if there's no answer in the remaining time, I will grant you the bounty as it seems you're the only one who tried to help. – hoefling Aug 19 '18 at 15:37
1

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)'
  ]
},
Ihor
  • 3,219
  • 2
  • 18
  • 20