How "nyc" works with "mocha" in test coverage - the basics

As a software developer, you have most likely written some tests to verify that your application not only functions according to what it was designed for but also does not misbehave or fail under certain conditions. However, one thing you could not have accurately determined by staring at the test results is the proportion of your source code that the tests cover.

There are different software packages that automate and report test coverage, depending on your preferred language. In node.js, one of the most commonly used tools is the npm nyc package, and in this write-up, I will be describing its basic usage with mocha.

A simple test script

{
  "scripts": {
    "test": "mocha test.js",
  }
}

In this script, mocha is the test framework being used, and test.js is the file containing the tests.

Running npm test on the command line will output the results of the tests. But to get the test coverage report, all you need to do is prepend the existing script with the nyc command, as shown below.

Test has coverage

{
  "scripts": {
    "test": "nyc mocha test.js",
  }
}

Now, what does the nyc command do?

Straight from the horse's mouth ...

this will simply instrument the code that your tests execute, and any subprocesses that it spawns

What this means is that nyc, analyzes your tests by inserting some functions into the test source code to measure the frequency and duration of function calls. The result of this analysis is then stored in a new directory called .nyc_output, located at the root directory of the project.

The .nyc_output directory is very important in that it is useful for generating test coverage report in different formats, such as HTML, text and lcov. Find an example below.

Generating reports

{
  "scripts": {
    "test": "nyc mocha test.js",
    "coverage": "nyc report --reporter=html --reporter=text --reporter=text-lcov"
  }
}

You will notice that in this example,

  • There is a new command report and the flag --reporter. In order to get an HTML or a lcov report, you will have to use alternative reporters which are the arguments passed to the --reporter flag. However, if you do not specify any argument, or omit the --reporter flag, you get the default text report.

Note: HTML coverage report is not outputted on the terminal, it is stored in a new directory called coverage, located at the project root directory.

  • The coverage script did not have to call the mocha command. This is not necessary as explained earlier because running npm test generates the .nyc_output directory, which is subsequently used by nyc to produce the various reports.

I have only scratched the surface of test coverage with nyc and mocha. If you would like to learn more about nyc configurations and other additional features, visit Istanbul.