Inside the coverage directory, you should find an index.html file; open it up in a web browser to continue:

At the top, you can see different percentages of test coverage. Here's what they mean:
- Lines: Percentage of the total lines of code (LoC) that were run.
- Statements: Percentage of total statements that were executed. If you always use a separate line for each statement (as is the case in our project), then Statements and Lines would have the same value. If you have multiple statements per line (for example, if (condition) { bar = 1; }), then there'll be more statements than lines, and the Statements coverage may be lower. The Statements coverage is more useful than Lines coverage; the Lines coverage exists for interoperability with line-oriented coverage tools like lcov. Note that you can use ESLint to enforce having one statement per line by enabling the max-statements-per-line rule.
- Branches: Imagine our code as a set of paths – if certain conditions are met, the execution of our program will follow a certain path; when a different set of conditions is employed, the execution will follow a different path. These paths diverge at conditional statements into branches. The branch coverage indicates how many of these branches are covered.
- Functions : The percentage of total functions that were called.
We can see that our overall Statements coverage is 91.84%, which is pretty good already. However, our handlers/users/create/index.js file seems to have only 66.67% coverage. Let's investigate why!
Click on the handlers/users/create link until you arrive at the screen showing the source code of the file:

A green bar on the left-hand side indicates that the line is covered. Furthermore, nyc will give you a count for how many times that line was executed over the entire run of our unit test suite. For example, the preceding res.status(201) line has been executed 8 times.
A red bar indicates that the line has not been executed. This can mean one of a few things:
- Our tests are insufficient and do not test all possible scenarios
- There's unreachable code in our project
Any other gaps in the coverage are indicated in the code itself as a letter enclosed inside a black box; when you hover over it, it will provide a more descriptive reason. In our case, there's a letter E, which stands for "else path not taken", meaning there's no test that covers what happens when the create function rejects with an error that is not an instance of ValidationError.
In our case, it actually highlights an error in our code. Inside the onRejected function of our then block, we are returning undefined if the error is not an instance of ValidationError. This will, in effect, return a resolved promise, and thus the catch block will never catch the error. Furthermore, we are also not testing for the case where the create function returns a generic error. Therefore, let's increase the test coverage for this module by fixing these two issues.
Before we do, let's commit our existing changes:
$ git add -A && git commit -m "Implement test coverage for unit tests"