Testing React Web Apps with Mocha (Part 2)

In the last post, we used Mocha to test a React app with JSX and ECMAScript 6 (Harmony).

In this post we’ll set up continuous testing on Travis-CI. We’ll also take advantage of our Mocha testing setup to track code coverage on every build.

If you want to skip straight to the finished product, check out this repo.

Running Tests on Every Commit

Tests are more effective when they’re run on every commit, allowing for a clear association between each test failure and the commit at fault.

The easiest way to do this for a GitHub project is with Travis-CI. To set this up, create a .travis.yml file like this one file and enable your project at travis-ci.org.

Why Code Coverage?

Running your tests on every commit is helpful, but how do you know that you’ve written enough tests? One way to answer this question is with code coverage, which tells you which lines of your code are executed by your tests.

(The red lines show that the failure case is untested.)

Code coverage can help guide your test writing. If one branch of an if statement is covered but the other isn’t, then it’s clear that you need to write a new test.

Writing tests isn’t always the most fun part of software development. Tracking test coverage over time adds a dash of gamification to the process: it can be motivating to watch the coverage percentage go up!

Generating Code Coverage Data

Generating code coverage data can be fairly involved. It requires instrumenting your code with counters that track how many times each line is executed. In fact, we don’t know of any way to do this for Jest tests, which we used before switching to Mocha. It’s also hard to generate coverage data with Mocha, but here we get to benefit from its extensive ecosystem: someone has already done the hard work for us!

We used Blanket to instrument our code for coverage:

npm install --save-dev blanket glob

We also had to add a blanket config section to our package.json:

"config": {
"blanket": {
"pattern": "src",
"data-cover-never": [
"dist",
"node_modules",
"tests"
],
"loader": "../../../tests/blanket-stub-jsx.js"
}
}

blanket-stub-jsx.js is a custom compiler that we had to write. As before, our decision to use JSX, Harmony and stubs has simplified our code but made the processes that operate on our code more complicated. This is a trade-off.

The "pattern": "src" tells Blanket where to find modules to instrument for coverage. If you don’t specify this, only files which are explicitly included by your tests will contribute to coverage. Untested files won’t count. Telling Blanket about them will reduce your test coverage percentage, but at least you’re being honest. And it will encourage you to write more tests for those untested files to bring that percentage back up!

Mocha includes a few “reporters” for displaying code coverage data. One of these is html-cov, which will generate an HTML page summarizing your code coverage:

./node_modules/.bin/mocha \
--require blanket \
--reporter html-cov \
tests/*test.js \
> coverage.html
open coverage.html

Here’s what it looks like:

(A web view of test coverage for BigComplicatedComponent.js. Note that this is the compiled code, not our original JSX/Harmony code. More on that below.)

Check out this repo for a fully-worked test setup based on the Jest/React example. The single test is in CheckboxWithLabel-test.js.

Tracking Code Coverage on Every Commit

Much like the tests themselves, code coverage works best when you track it on every commit. If you don’t, coverage might drop without your realizing it.

coveralls.io is a test coverage site which is free for open source projects and integrates nicely with GitHub and Travis-CI. So long as you can produce coverage data in the correct format, coveralls will track the changes in your project’s test coverage, generate badges for your project and provide a nice test coverage browser.

Coveralls works best when you send it coverage data directly from a Travis worker. To set this up we installed a few NPM packages…

npm install --save-dev mocha-lcov-reporter coveralls 

… and added this bit to our .travis.yml file’s script section:

./node_modules/.bin/mocha \
--require blanket \
--reporter mocha-lcov-reporter \
tests/*test.js \
| ./node_modules/coveralls/bin/coveralls.js

Here’s what the code coverage data looks like on coveralls:

(Coverage of BigComplicatedComponent. Note that its render method is never called, because it’s stubbed in the test.)

It’s worth noting that coverage is measured on the transpiled JavaScript code, but displayed against the original code on Coveralls. This only works because the JSX/Harmony compiler preserves line numbers.

Conclusions

Continuous code coverage is one of the big wins of using Mocha to test React apps. It takes a bit of work to set up, but the motivation it gives you to write more tests is well worth the effort.

If you have any issues or ideas regarding this setup, please file an issue on our example repo.