mdoery ~ software development

adventures in coding

code coverage for node and vows

| Comments

Summary: you can get code coverage stats for your node.js code

(FYI my dev box uses Ubuntu Linux 13.10.)

I’ve been developing new features in my node.js application, and concurrently writing vows.js tests for the new code. Yesterday, I decided that it was about time that I check to see just how much code my tests are covering.

What to do? When developing Java software with the eclipse IDE, it’s relatively simple to get code coverage information for your JUnit tests. With node, things are more complicated.

I looked at code coverage in npm and saw a number of potentially useful libraries, but didn’t want to research each one to see if they worked with vows. Then I noticed that the vows page says “Code coverage reporting is available if instrumented code is detected. Currently only instrumentation via node-jscoverage is supported.” Well, that makes it a no-brainer. They give you instructions for downloading and installing node-jscoverage, which is not in npm!

While I was hunting around, I had found Alex Seville’s post about some problems he had encountered using node-jscoverage. That made me concerned that the instructions on the vows page were incomplete. So I followed his directions. In his step 2, I ran into a little permission trouble; I had to run each command as sudoer:

1
2
3
sudo ./configure
sudo make
sudo make install

From then on, almost everything worked. Here’s my node.js app code:

1
2
3
/srv/app/node-app
/srv/app/node-tests
/srv/app/node_modules

And here’s how I produced the instrumented code to test:

1
jscoverage /srv/app/node-app /home/mdoery/instrumented/node-app

Notice I put my instrumented code into a directory which is completely independent from my app directory structure. You don’t want instrumented code running in your app! It’s only used for generating coverage reports.

I followed Alex’s link to Jeff Kunkle’s post about switching between testing instrumented and non-instrumented code. I grabbed Jeff’s sample code to do this, and it worked like a charm. Then I ran a test –

1
2
3
4
5
6
7
8
9
10
11
12
/srv/app/node-tests$ ../node_modules/vows/bin/vows test-something.js
ERROR   => Error: Cannot find module 'moment'
  at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at exports.undefined.window.C (/home/mdoery/instrumented/node-app/C.js:208:22)
    at Object.<anonymous> (/home/mdoery/instrumented/node-app/C.js:607:3)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)

Oops! The instrumented code couldn’t find my app’s libraries (such as moment) in /srv/app/node_modules. So I created a soft link to these in my instrumented directory:

1
ln -s /srv/app/node_modules /home/mdoery/instrumented/node_modules

After doing that, my instrumented code appeared to run fine; I got the usual happy output from vows:

1
2
3
/srv/app/node-tests$ ../node_modules/vows/bin/vows test-something.js
·············
  ✓ OK » 13 honored (0.004s)

But how could I be sure that the instrumented code was being exercised? This time, I reran my test with the --cover-html option:

1
../node_modules/vows/bin/vows test-something.js --cover-html

Sure enough, I saw a file called coverage.html had been generated in my current directory. I opened it in my browser window to view an html display of what code is covered, and what still needs to be tested. Nice!

Comments