Using NodeJS/Mocha together with SonarSource/JavaScript plugin

July 2, 2012    code analysis code coverage JavaScipt Mocha NodeJs Sonar unit tests

Note: there has been an update. The pull request was rejected, but TJ Holowaychuck built a way to use custom reporters. See the end of the article for more information.

Lately I have been busy with NodeJS; you can see some of my work on GitHub. To keep code quality on par, several tools are available. For example, you can use jshint or jslint to perform static analysis on your JavaScript code. In case of static analysis, code is looked at, but never executed.

Another tool is SonarSource. I will not try to explain SonarSource, as they are much better at it themselves. To perform analysis on JavaScript, the JavaScript plugin for SonarSource can be used.

For unit testing, I usually use expresso. Expresso is a neat unit testing framework. It can even provide code coverage (a form of dynamic analysis) metrics. Expresso, however, seems to be no longer worked on. Instead, Mocha is the successor to expresso. Both are written by TJ Holowaychuck. Mocha is a more elaborate. For example, it provides several reporters which can be used to output the test results, and coverage details, to different formats.

The SonarSource/Javascript plugin named earlier supports both static analysis and dynamic analysis. For the dynamic analysis, JsTestDriver is used. JsTestDriver saves the test results in the jUnit/xUnit format, while the code coverage results are saved in the LCOV format.

Mocha has the xUnit reporter which saved the test results in a JUnit compliant format. Mocha does not have a reporter which writes the test results to the LCOV format. Therefore, I have written a new LCOV reporter for Mocha. It currently is a pull request, but hopefully it will be integrated in the Mocha tree soon.

First, lets install the new LCOV reporter for Mocha:

  • download the file;
  • place the file in the same directory as the other Mocha reporters. On my laptop with OSX/macports/npm, the directory is /opt/local/lib/node_modules/mocha/lib/reporters;
  • test mocha by running: mocha –reporter lcov. If you get no error, the reporter is installed correctly.

Then, lets alter a project to let Sonar analyze it. As an example, see the mco project. It is assumed that you already have installed SonarSource, with the Javascript plugin.

First, we need to store the results to a file. Doing so can easily be done without any modifications by running the command:

$ mocha -R xunit > TEST-all.xml

This results in a file called TEST-all.xml.

Second, we need to get the code coverage. Doing so is a bit harder, as we first need to ‘instrument’ the code to get the code coverage data. This is done using the node-jscoverage command. Then, we need to replace the original code by the instrumented code, and execute mocha with the new LCOV reporter. The following snippet shows this:

$ node-jscoverage lib lib-cov
$ mv lib lib-orig
$ mv lib-cov lib
$ mocha -R lcov  > coverage/coverage.lcov
$ mocha -R xunit > coverage/TEST-all.xml
$ rm -rf lib
$ mv lib-orig lib

After executing this, we should have a file called coverage.lcov in the directory coverage, as well as a TEST-all.xml file. The file used can be found here.

Finally, we need to create a file. See the in the mco proejct for an example. The two important properties are: sonar.javascript.jstestdriver.reportsfolder and sonar.javascript.jstestdriver.coveragefile. The first propertie specifies where to look for the data, the second property specifies what the LCOV file is called.

After running the sonar-runner, you should have a project in Sonar, including test coverages screenshot for some an analysis on the MCO project. Screenshot of MCO-project in sonar

Happy coding.

Update: TJ Holowaychuck built a way to use custom reporters. At the time of writing, the HEAD-version in GitHub is not yet published on Npm, but this will probably be done soon. To use the LCOV reporter, install the mocha-lcov-reporter module through npm. Then, call Mocha as follows:

$ mocha --reporter mocha-lcov-reporter

This should give the coverage in the LCOV format.