How to Measure Your JavaScript Code Coverage With Istanbul

When it comes to code quality, we often tend to think about robust test suites going all over the steps of the testing pyramid. While having unit, integration, and acceptance tests in place can greatly enhance the quality of your product, this is only one part of the equation.

How do you know if you’ve really covered everything? You’ve ensured the quality of your code with your test suite, but how can you ensure your test suite also has good quality?

JavaScript Course

Code coverage helps you with that. It helps you understand how much of your codebase is covered by tests. We’ll explore why you should care and how you can integrate Istanbul —the self-proclaimed simplest JavaScript code-coverage tool — into your application.


Why You Should Measure Code Coverage

So why should you measure code coverage in the first place? Let’s go over some points where code coverage could help you produce a better product.

First and foremost, it improves the quality of your test suite. Having a robust test suite in place ensures that your codebase contains little to no bugs, while having a code-coverage tool in place ensures that these tests are also covering everything they need. Keep in mind that coverage tools only look at the number of lines executed by a test case. It won’t know whether your test is testing the right thing.

You can also enforce a minimum threshold. Say you have a threshold of 80%. This means you need to have 80% of your codebase tested in order to produce a green test. This way, you can fail deploys to prevent breaking changes to break your application.

Most importantly, you’ll see visually which part of your code isn’t covered by tests. This makes it easy to spot weak spots and see which part of your app needs to be better maintained.

The coverage look of Istanbul
Visual feedback on which lines of code are not covered by tests

How to Integrate Istanbul Into Your App

To get Istanbul up and running, we’ll need two things: a testing suite with some test cases that we can run the tool against, and secondly, we need to install it as a dependency unless you are using Jest. To save some time, I’ll use this boilerplate from a previous tutorial. It has some test cases written in Jest. You can clone it from the link above.

The Jest project setup
The project structure

If you’re not using Jest, you need to run npm i --save-dev nyc to install Istanbul after you’ve cloned the repository.

Configuring Jest to collect coverage

Open the config.js inside tests/unit, and add the following line:

 module.exports = {
     rootDir: '../..',
+    collectCoverage: true,
     testURL: 'http://localhost',
     testEnvironment: 'jsdom',
     testMatch: [
         '<rootDir>/tests/unit/*.(spec|test).(j|t)s'
     ]
 };
config.diff
Copied to clipboard!

This enables code coverage for Jest. You can run the test suite with npm run unit. But before doing that, x out the very last test in AppController.spec.js. Otherwise, we get 100% coverage, and we won’t be able to see how Istanbul tells us which part of the code hasn’t been covered yet.

After the tests are finished, you’ll be greeted with a coverage folder generated into your project root.

the generated coverage report folder by Istanbul
The generated coverage report folder

Open the index.html file; this holds the generated report for all files.

The generated report by Istanbul
The generated report by Istanbul

Next to each line, you’ll see how many times a function has been executed by a test case. For the add method, we have eight different cases, so it has been covered eight times. But divide wasn’t covered by anything, as we turned off the test. Istanbul highlights everything with red to make it easy to spot uncovered parts.

Adding thresholds

Adding thresholds is just as easy. As you can see from the GIF above, we can add a threshold to four different categories: statements, branches, functions, and lines. To add a global configuration of 80%, open your config.js and add the following:

 module.exports = {
     rootDir: '../..',
     collectCoverage :true,
+    coverageThreshold: {
+        global: {
+            statements: 80,
+            branches: 80,
+            functions: 80,
+            lines: 80
+        }
+    },
     testURL: 'http://localhost',
     testEnvironment: 'jsdom',
     testMatch: [
         '<rootDir>/tests/unit/*.(spec|test).(j|t)s'
     ]
 };
config.diff
Copied to clipboard!

You can add a rule to each category separately. This will apply the threshold globally, for every file. And if the 80% isn’t met, Jest will fail. If you want to have custom rules for separate files or folders, you can also do that.

coverageThreshold: {
    global: {
        statements: 80,
        branches: 70,
        functions: 80,
        lines: 80
    },
    "../../src/AppController.js": {
        branches: 80,
        statements: -10
    } 
}
config.js
Copied to clipboard!

You need to pass the path to the file and define your thresholds there. You can also provide negative values. This means the maximum number of uncovered statements can’t be greater than 10. And that’s it — you’ve just integrated Istanbul into your test suite!


Summary

Istanbul provides an easy way to understand where your test suite needs improvements. It takes no more than a couple of hours from your day to set it up properly. But once it’s done, the invested time is greatly returned. It helps you produce a better test suite and with it, a better product.

If you’d like to learn more about Istanbul — or you’re using a test suite other than Jest — I’d like to encourage you to take a look at their official website. It’s super easy to set up for other frameworks as well.

Thank you for taking the time to read this article — happy configuring!

JavaScript Course
Remove ads
Remove ads

📚 Get access to exclusive content

Want to get access to exclusive content? Support webtips with the price of a coffee to get access to tips, checklists, cheatsheets, and much more. ☕

Get access Support us
Remove ads Read more on
Remove ads
Remove ads
🎉 Thank you for subscribing to our newsletter. x