.

Tags:

These days, having enough unit tests for a JavaScript-based web application/library is the bare minimum. Ideally, the code coverage of those tests is also monitored in a day-to-day development situation. Fortunately, this is easy to do with a modern test runner such as Venus.js.

Named after the famous Venus flytrap, Venus.js was originated at LinkedIn Engineering group to facilitate its JavaScript testing activities. Venus.js is pretty comprehensive, it supports unit tests written for a number of test libraries: Mocha (default), Jasmine, and QUnit. Venus.js is easy to install and to use, I recommend reading its excellent Getting Started tutorial.

For the demonstration of code coverage, I prepare a Git repository bitbucket.org/ariya/coverage-istanbul-venus. If you want to follow along, just clone it and check its contents.

First, let’s take a look at the code we want to test. This is just a DIY implementation of the square root function, it can’t be simpler than:

var My = {
    sqrt: function(x) {
        if (x < 0) throw new Error("sqrt can't work on negative number");
        return Math.exp(Math.log(x)/2);
    }
};

In order to maximize the test coverage, the unit tests for the above My.sqrt() function needs to check for normal square root operation and also when it is supposed to throw an exception. This is available in the test/test.sqrt.js file (based on Mocha) which looks like the following:

/**
 * @venus-library mocha
 * @venus-code ../sqrt.js
 */
describe("sqrt", function() {
  it("should compute the square root of 4 as 2", function() {
    expect(My.sqrt(4)).to.equal(2);
  });
});

One notable feature of Venus.js is its zero-configuration design. In the above example, we don’t need to write any HTML to serve the code and the test. Venus.js uses an annotation approach. You can see the use of @venus-code to specify the file containing the code we want to test (i.e. the implementation of My.sqrt) and @venus-library to choose the testing library (i.e. Mocha). Everything else will be taken care of automatically.

If Venus.js is properly installed, executing the test is a matter of running:

venus test/test.sqrt.js -e ghost

which gives the following result:

venusjs

In the test invocation, the option -e ghost indicates that the tests are to be executed headlessly using PhantomJS (again, another nice built-in feature of Venus.js). Of course, Venus.js supports other testing environments and it can run the tests on real web browsers or even via Selenium Grid or Sauce Labs.

How to show the code coverage of the tests? It is a matter of adding another option:

venus test/test.sqrt.js -e ghost --coverage

Behind the scene, Venus.js uses Istanbul, an excellent JavaScript instrumentation and code coverage tool. Running the test with coverage tracking will add a few more lines of report. Thanks to Istanbul, all three types of code coverage (statements, functions, branches) will be tracked accordingly.

venuscoverage

Another very useful feature of Venus.js is the ability to mix-and-match tests written using a different library. This is illustrated in the example repo. Instead of only test/test.sqrt.js, you also spot two additional files with their own set of unit tests: test/test.extensive.js and test/test.error.js. The former adds more checks on the square root functionality (probably excessive, but you got the point) while the latter detects some more corner cases. What is interesting here is that test.extensive.js relies on Jasmine while test.error.js is written using QUnit.

If you check the package manifest, what npm test actually runs is:

venus test --coverage -e ghost

In other words, Venus.js will locate all the test files in the test/ directory and execute them. In this case, we have three (3) test files using different test libraries and Venus.js will handle them just fine. Isn’t it nice?

In the past, I have explained the use of Karma and Istanbul to track code coverage of JavaScript unit tests written using Jasmine, QUnit, and Mocha. However, if Karma is not your cup of tea or if your different subteams would like to use different test libraries, then perhaps Venus.js can be the solution for you.

Have fun trapping those bugs!

  • Tianyi33

    Hi, just wonder is there any major difference between Karma and Venus?

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Config file vs annotation is one major difference.

  • Matthew Kastor

    This is pretty cool stuff to run locally but I like having my JavaScript tests run from an HTML page on GitHub. With Jasmine I can do it for any client side JS without spinning up a server. I do like the annotation replaces config files approach, it looks like it would make things much easier to manage. I love that it has support for phantomjs built in because phantomjs is awesome, so awesome. :D

  • SimpleMonk

    Pretty cool! Does it work with Browserified and concatenated single spec file???