Collecting JavaScript code coverage with Capybara in Ruby on Rails application JetThoughts Follow Apr 6 · 3 min read

Having JavaScript code covered by Capybara system tests, can we utilize them for the code coverage collecting and get the aggregated result with the coverage from the unit tests?

We want to be sure that all code responsible for key user journey scenarios of our app is covered with tests.

For example, there is a Ruby on Rails application that uses Webpacker and has JavaScript files that are covered by the system tests. Capybara is used as the system testing tool.

How to get code coverage combining the results of system and unit tests?

Inject getting coverage for JavaScript code

For getting coverage of the JavaScript code, we use Istanbul Instrumenter Loader. It needs to be added as a dev dependency with the package manager (Link to installation).

This instrumenter is already outdated, but Jest is still using it to get coverage, and we have not found any alternatives to work with Webpack directly.

The Istanbul Instrumenter Loader will be run on the Webpack compilation stage for the test environment. So we placed it in the webpack folder.

Getting coverage after testing in the browser

After running the system test, the browser stores the coverage value in the global variable _coverage_. We need to extract from the page and save it.

This helper will store the coverage value from the _coverage_ variable into the JSON file. We need to call it after each system test.

Aggregate the coverage values

For collecting the coverage results we will use Codecov. It has several arguments in his favor:

aggregate the coverage results for different code parts (e.g. Ruby and JavaScript) in one place.

manage the reports from the Istanbul Instrumenter Loader

allow merging the coverage reports from several sources

Here is the example of a script that prepares the compilation with the Istanbul Instrumenter, runs the system tests, aggregates the code coverage results and sends the report to Codecov:

After system tests running,

bin/rails test:system

we’ll have a bunch of generated JSON files in the e2e_coverage folder containing coverage reports for the JavaScript code. Each file corresponds to one test.

At the next stage, they are merged into one JSON file. For this purpose, we use nyc (Istanbul’s command line interface).

This is a more advanced tool for collecting coverage, but it does not allow us to build a report because it does not work with Webpack directly. We can take advantage of the useful property that it supports — the merge command.

npx nyc merge ./e2e_coverage coverage.json

Finally, the aggregated report is sent to the Codecov with e2e flag:

npx codecov -f coverage.json -F e2e

And that’s all — we just got the JavaScript coverage without writing any actual JavaScript tests.