ariya.io About Talks Articles

JavaScript Code Coverage with Istanbul

3 min read

Achieving a good code coverage is a useful practice in today’s software craftsmanship. For JavaScript applications, whether it is for the browser or for the server, many tools to check the statement coverage are available. What about branch coverage? Fortunately, such a tool is finally available: Istanbul.

Made by Krishnan Anantheswaran from the YUI team Yahoo! Cocktail team, Istanbul is extremely easy to use. It is suitable for both browser-based instrumentation or Node.js application analysis. Under the hood, Istanbul uses Esprima to parse JavaScript code and Escodegen to generate the instrumented version of the code. Istanbul is pure JavaScript, there is no native code or other kind of native libraries wrapper involved.

Istanbul requires Node.js, the package can be installed as:

npm install istanbul

Using Istanbul with command-line Node.js application is fairly straightforward. Assuming you have test.js like this:

x =42;
if(false)
     x =-1;

We can analyze the coverage by running:

istanbul cover test.js

which gives the following outcome:

=============================== Coverage summary ===============================
Statements   : 66.67% ( 2/3 )
Branches     : 50% ( 1/2 )
Functions    : 100% ( 0/0 )
Lines        : 66.67% ( 2/3 )
================================================================================

Even if you put all the above code in just one line, Istanbul can still give the correct coverage result. This is because Istanbul does not work based on line-by-line coverage, it does fully understands JavaScript syntax. Beside the quick text-based report, Istanbul also produces the coverage report in LCOV format. This way, the coverage report can be nicely shown, with color coding and other fancy features:

What about something more complicated? I wrote some time ago about the trap of checking only statement coverage, the example which demonstrated that is the following fragment. Now, if your unit test only verify the result of running inc(4) and you forgot you also need the check for inc(4,2), you won’t see the bug easily. This example is of course just an oversimplified example, in real-world application the problem is much harder to spotted.

function inc(p, q){
    if(q ==undefined) q =1;
    return p + q/q;
}

However, if we run Istanbul so that we can see the branch coverage, the report reveals the issue. Here the marker ‘E’ indicates that the else path of the branch is never executed and that should provoke a suspicion.

How does Istanbul work under the hood? It takes a JavaScript program and passes it through Esprima to get the syntax tree. Then, it injects some instrumentation by wrapping various syntax constructs. After that, a new JavaScript program is generated from the syntax tree by using Escodegen. When the program runs, the injected annotation is also executed accordingly and thereby the statistics of the program execution can be gathered.

While Istanbul has a mechanism to automate running Node.js application with instrumentation, nothing stops you from using the instrumented code in other JavaScript environments (such as web browsers). For this purpose, Istanbul has a special instrument command to perform only the instrumentation. It is up to you to process the coverage hooks and reports.

With Istanbul, tracking JavaScript code coverage has never been easier!

Related posts:

♡ this article? Explore more articles and follow me Twitter.

Share this on Twitter Facebook