376

I am using Mocha for testing my NodeJS application. I am not able to figure out how to use its code coverage feature. I tried googling it but did not find any proper tutorial. Please help.

Charles Merriam
  • 19,908
  • 6
  • 73
  • 83
tusharmath
  • 10,622
  • 12
  • 56
  • 83

4 Answers4

510

You need an additional library for code coverage, and you are going to be blown away by how powerful and easy istanbul is. Try the following, after you get your mocha tests to pass:

npm install nyc

Now, simply place the command nyc in front of your existing test command, for example:

{
  "scripts": {
    "test": "nyc mocha"
  }
}
vasilyrud
  • 825
  • 2
  • 10
  • 18
Dan Kohn
  • 33,811
  • 9
  • 84
  • 100
  • 32
    And if you're running a locally installed version of mocha, try `istanbul cover node_modules/mocha/bin/_mocha`. – Eric McCarthy May 20 '13 at 04:45
  • 105
    Or, install both istanbul and mocha locally, and add the following to the scripts section of your package.json and then just npm run coverage: "coverage": "./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- --ui bdd -R spec -t 5000 – Dan Kohn May 20 '13 at 04:49
  • has anyone tried this using grunt and coffeescript? I've looked into grunt-mochacov which works fine in linux but not windows (and its using blanket which didnt seem overly functional to me) –  Nov 27 '13 at 18:35
  • 2
    https://github.com/daniellmb/grunt-istanbul-coverage or https://github.com/taichi/grunt-istanbul should work for you. And here is Coffeescript and Istanbul: https://github.com/Constellation/ibrik – Dan Kohn Nov 27 '13 at 19:47
  • 6
    I had trouble getting this command to run on windows, but by specifying the full path to the mocha bin I was able to get it to work. `istanbul.cmd cover C:\Users\{UserName}\AppData\Roaming\npm\node_modules\mocha\bin\_mocha` – Jason Jarrett Dec 09 '13 at 22:53
  • @JasonJarrett I highly recommend installing Git Bash (most easily gotten via Github for WIndows). You'll find that most commands run correctly. – Dan Kohn Dec 10 '13 at 03:38
  • 4
    `$(npm bin)` is a canonical shortcut to `./node_modules/.bin/`, and `istanbul/lib/cli.js` is aliased to `istanbul` in the bin folder. So here's a shorter command: `$(npm bin)/istanbul cover $(npm bin)/_mocha -- --ui bdd -R spec -t 5000` – Henry Blyth Nov 13 '14 at 13:10
  • 19
    @ Windows users: `istanbul cover node_modules/mocha/bin/_mocha -- -R spec` – Pier-Luc Gendreau Dec 17 '14 at 07:42
  • One more minor note to make this idiot proof might be the use of "--recursive" – nick Feb 21 '15 at 17:22
  • Please note that istanbul actually parses the AST, and therefor if you have comments in your code for various things these will be removed. I spent about 2 hours troubleshooting istanbul only to have to ultimately back out and find a new solution. – Ron E Mar 11 '15 at 23:45
  • You can also use https://www.npmjs.com/package/gulp-istanbul. It has option to specify https://www.npmjs.com/package/isparta as an instrumenter which provides code coverage for ES6. – Kunal Kapadia Oct 13 '15 at 22:24
  • 1
    Please note that "coverage":"istanbul cover _mocha" in package.json will not work, as it will refer to ./node_modules/.bin/_mocha instead of ./node_modules/mocha/bin/_mocha where first is a shell script and the later is a js – qbolec Dec 15 '15 at 17:53
  • 1
    It gives me this error: `$ istanbul cover _mocha -- -R spec No coverage information was collected, exit without writing coverage information C:\Users\Ulysses\AppData\Roaming\npm\_mocha.CMD:1 (function (exports, require, module, __filename, __dirname) { @IF EXIST "%~dp0 ^ SyntaxError: Unexpected token ILLEGAL ` How can I solve this please? – Ulysses Alves Dec 16 '15 at 18:17
  • 1
    @UlyssesAlves Looks like you are running a windows OS, like @Pier-Luc Gendreau mentioned you will need specify ```istanbul cover node_modules/mocha/bin/_mocha -- -R spec``` Source: https://github.com/gotwarlost/istanbul/issues/90 istanbul assumes that the _mocha you specify translates to a JS file which is true in non-windows environments. In a windows environment, this is likely a batch file that is getting loaded by node and, of course, fails. – Siva Kandaraj May 18 '16 at 03:53
240

Now (2023) the preferred way to use istanbul is via its "state of the art command line interface" nyc.

Setup

First, install it in your project with

npm i nyc --save-dev

Then, if you have a npm based project, just change the test script inside the scripts object of your package.json file to execute code coverage of your mocha tests:

{
  "scripts": {
    "test": "nyc --reporter=text mocha"
  }
}

Run

Now run your tests

npm test

and you will see a table like this in your console, just after your tests output:

Istanbul Nyc Mocha code coverage

Customization

Html report

Just use

nyc --reporter=html

instead of text. Now it will produce a report inside ./coverage/index.html.

Report formats

Istanbul supports a wide range of report formats. Just look at its reports library to find the most useful for you. Just add a --reporter=REPORTER_NAME option for each format you want. For example, with

nyc --reporter=html --reporter=text

you will have both the console and the html report.

Don't run coverage with npm test

Just add another script in your package.json and leave the test script with only your test runner (e.g. mocha):

{
  "scripts": {
    "test": "mocha",
    "test-with-coverage": "nyc --reporter=text mocha"
  }
}

Now run this custom script

npm run test-with-coverage

to run tests with code coverage.

Force test failing if code coverage is low

Fail if the total code coverage is below 90%:

nyc --check-coverage --lines 90 

Fail if the code coverage of at least one file is below 90%:

nyc --check-coverage --lines 90 --per-file
lifeisfoo
  • 15,478
  • 6
  • 74
  • 115
  • 3
    This works perfectly for jasmine also : "nyc --reporter=html jasmine" – Sandip Subedi Aug 15 '17 at 14:18
  • mine works but I do not see the code coverage showing which lines are covered by green / red in the code itself. – PositiveGuy Jan 21 '18 at 07:18
  • 14
    thanks for adding "now(2017)" - really helpful in this fast moving javascript world – kamahl Feb 01 '18 at 09:43
  • 3
    In case anyone else was confused - the npm repository [istanbul](https://www.npmjs.com/package/istanbul) seems to have been superceded by [nyc](https://www.npmjs.com/package/nyc). Per its listed dependencies, istanbul was split apart into various packages which are all maintained in their [istanbuljs monorepo](https://github.com/istanbuljs/istanbuljs) – aaaaaa Apr 19 '18 at 15:29
  • 1
    I am having the `--reporter=html` enabled but the html file is empty always, there is nothing shown about uncovered blocks or % covered etc just headers of the table – TGW May 02 '18 at 07:36
  • `npm run test-with-coverage` fails with `(function (exports, require, module, __filename, __dirname) { import _ from 'lodash'^^^^^^`. – technerd Jul 08 '19 at 09:52
  • Nice this is a useful response, @lifeisfoo; It seems to be more up-to-date than this medium article: https://medium.com/the-node-js-collection/rethinking-javascript-test-coverage-5726fb272949 Does anyone have any thoughts on c8 vs istanbul? Just based on ease-of-use I'm leaning towards istanbul. – Vee Sep 28 '19 at 20:36
  • Make sure to put `--reporter` or other params of `nyc` right after `nyc` and not after `mocha` or whatever else you're using. – thisismydesign Jan 02 '20 at 22:15
  • If your test get stuck after tests completion and don't show the coverage report. Add `--exit` parameter at the end. `test-cover": "nyc mocha --exit"` – Joel Aug 31 '21 at 00:44
  • Note: This doens't work with ESM modules. C8 seem to be the new best option. – Digicrat Jan 08 '22 at 03:26
20

Blanket.js works perfect too.

npm install --save-dev blanket

in front of your test/tests.js

require('blanket')({
    pattern: function (filename) {
        return !/node_modules/.test(filename);
    }
});

run mocha -R html-cov > coverage.html

jsan
  • 2,794
  • 2
  • 18
  • 25
  • require('blanket')({ pattern: function (filename) { return !/node_modules/.test(filename); } }); – jsan Apr 01 '14 at 21:08
  • 6
    As of 2015, blanket.js is not maintained anymore and doesn't support ES6. Istanbul is highly recommended. – teroi Oct 09 '18 at 10:57
14

The accepted answer (nyc) does not work if you are using ESM modules.

C8 appears to be the best solution now, which leverages built-in NodeJS capabilities and utilizes istanbul (like nyc, and shares the same config files).

npm install -g c8
c8 mocha

It will use .nycrc for configuration. A sample configuration I'm using is:

{
    "all": true,
    "exclude": ["test"],
    "output": "reports",
    "reporter" : [
        "html",
        "text"
    ]
}

(Note: I was pointed to c8 by an answer to another question https://stackoverflow.com/a/69846825/1949430)

Digicrat
  • 581
  • 5
  • 13
  • It worked really well for me, even with lots of added mocha parameters, e.g. from my package.json: { "scripts": { "test": "mocha --reporter=spec --recursive test/spec", "coverage": "c8 mocha --reporter=html --recursive test/spec", ... ... ... – RobertG Nov 11 '22 at 22:34