Lesson Sunday

With our test driven development approach, we should have 100% testing coverage of our business logic. What do we mean by testing coverage? Well, if we have ten lines of code and our tests only "hit" five lines of code, then we'd have 50% coverage. If there is a function or another piece of code that's untouched by our tests, it won't be included in the test coverage.

Jest can give us information about test coverage if we add the --coverage flag to the "test" script in our package.json file:

package.json
...
"scripts": {
    ...
    "test": "jest --coverage"
  },
...

Now let's see what happens when we run our tests:

Our tests now include test coverage.

Our tests now include a chart that shows our total test coverage. It specifies the file (triangle.js) as well as the percentage of statements, branches, functions and lines that are covered. We have 100% test coverage, which is what we should be aiming for. The final column - for Uncovered Line #s is blank. This column will show all lines that aren't covered in our tests.

Here's how the test coverage looks if we comment out our test for an equilateral triangle.

Our test coverage shows slightly less coverage.

Now we can see that a line has been added to the Uncovered Lines # section. Our test coverage will show us exactly which lines aren't covered in our code so we can check them and then add tests if needed. Since we are using TDD, we should always have 100% coverage - but this is a great way to confirm that our coverage is complete.

Note that the coverage chart is mostly showing green - that's because our coverage is still considered good. Many enterprise companies won't have that level of coverage for their tests. Once again, though, because we are using TDD and our projects are small, we expect to hit 100%.

Ultimately, the most important columns to pay attention to are the last two. We want % Lines to be 100. If it's not, we should check the line numbers in Uncovered Line #s.

The other columns can be a bit confusing. For instance, we have 100 for % Funcs because our tests have hit both of our functions - not because they are fully tested. This column can be misleading so it's not as helpful.

The % Stmts refers to the percentage of statements that are covered. We have 11 total statements in our code. Generally, it will be the same as the line number - though if there are multiple statements on a line, then it could be different. In this case, we'd need to make sure we have 100% coverage on this line as well.

The % Branch can also be confusing. We only have four branches so how are we getting 92.86% coverage? This coverage is based on the percentage of paths our tests are not hitting as they go through our code. There are 14 paths through our code, 13 which are covered. Generally, this percentage number is not as useful for us.

That's why it's best to keep things simple. It should be 100% across the board - if it's not, check the Uncovered Line #s to see which lines aren't covered.

Keep in mind also that the coverage isn't foolproof. For instance, if we comment out our test for constructor properties, we'll still get 100% coverage across the board. That is because all of our other tests rely on the constructor - so our tests are hitting every line of code. However, we should always test our constructors separately - and we should always endeavor to test every behavior in our code.

For that reason, we can't assume that everything is perfect just because our coverage shows 100%. We still need to have good TDD practices in place. However, we can and should assume that we have more testing to do if we don't have 100% - so it's an excellent tool for ensuring that we have at least some coverage for every line of code.

Finally, when we run our tests with the --coverage flag, Jest will generate an HTML report in a directory called coverage. This directory should be added to our .gitignore file:

.gitignore
...
coverage/

We can go to coverage/lcov-report and then open its index.html file in the browser if we want a nicer looking version of our tests.

Our coverage information looks nicer in the browser.

As we can see here, we get a little more information as well, such as the exact number of statements and paths we have in our code.

Note: If you're using a version of Jest where the coverage directory isn't automatically generated, you'll need to update your package.json file:

package.json
...
"scripts": {
    ...
    "test": "jest --coverage"
  },
"jest": {
    "collectCoverage": true,
    "coverageReporters": ["html"]
  },
...

We just have to pass in a configuration for Jest with "collectCoverage" set to true. Then we have to specify that the "coverageReporters" should be ["html"]. (We could also specify other coverage reporters as well.) It's yet another way we can update our package.json file to configure our environment further.

In this lesson, we've looked at how Jest's coverage tools can give us more information about how thoroughly we are testing our code. While this tool can be very helpful for ensuring our tests cover every line in our business logic, they aren't a replacement for good TDD practices.

Lesson 30 of 43
Last updated October 21, 2021