Generating Code Coverage Report for Cypress

Updated: 5 days ago

One of my technical tasks last week at Zoopla was to integrate code coverage for Cypress so we can see which parts of the code are overly tested and which parts are not tested. We're currently trying to refactor the Cypress tests that we have and this will help us understand which tests we can delete and tests that perhaps we need to add. While code coverage is not the best measure for checking that we have written a great test nor it also doesn't measure that our tests are credible, it does give a visual indicator to see which areas of our code has been overly tested and which areas have not been tested at all.

The first thing that I did was look at Cypress' code coverage documentation which was very informative. If you are not familiar with how code coverage works in a nutshell, I shall explain it briefly 😊

How does Code Coverage works?

Code coverage tools work by scanning your application's source code and inserting additional counters to different branches, statements, lines and functions. Every time your automated tests hit different areas on the code base, the counters will increment. Once the tests finished, the total number of hits will then be recorded against the total number of possible hits.

The below diagram is a simple example of a code coverage report showing the hit percentages on statements, branches, functions and lines.

Code coverage report showing the hit percentages on statements, branches, functions and lines.
Code Coverage Report from Istanbul

Installing Required Dependencies

The first thing that we need to do is install the dependencies that we need to get going. On this post, I'll be using babel-plugin-istanbul and cypress/code-coverage plugins.

Let's install that by adding the following packages to our project.

Installing babel-plugin-istanbul and @cypress/code-coverage via yarn or npm.
Installing required plugins via npm or yarn

Instrumenting Your Code

As per Cypress documentation, there are two ways of instrumenting code coverage.

  1. Via nyc's instrumented feature which is done by running a command on your terminal which will then produce instrumented source files.

  2. Via babel-plugin-istanbul which is done during your code transpilation if your project is already using babel.

Since our project is using babel already, I opted for using babel-plugin-istanbul and added the following plugin to our .babelrc file to instrument our code base. However, Jest already uses istanbul so using babel-plugin-instanbul will result in a duplicate plugin error. To fix this, I used the "env" options from babel to allow nested configuration. If the environment name matches the key provided, the babel-plugin-istanbul will be used. In this example, I created a new environment key called "e2e".

JSON file showing how to setup istanbul plugin to your babel file.
Adding istanbul plugin to babel

Setting up Cypress Code Coverage

This is actually quite straightforward to do. First, add the following import statement to your cypress/support/index.js file

Import statement to add code-coverage to our cypress/support/index.js file
Importing code-coverage plugin to Cypress

Next, update your cypress/plugins/index.js file to register the code coverage plugin into your Cypress tests.

Code configuration needed to add to plugins/index.js file to load the code coverage task in Cypress.
Register code coverage task to Cypress

In order to use the babel-plugin-istanbul from our babelrc file, let's set the BABEL_ENV to e2e on our cypress.json file.

Code showing how to set BABEL_ENV to have the value of e2e on cypress.json.
Additional configuration on cypress.json

Now, when I ran our Cypress tests, I see additional commands (before and after hooks) on the test runner that code coverage is being collected and a report is generated automatically on `coverage/lcov-report/index.html` 🎉

Combining Jest and Cypress Code Coverage Reports

The last step that I needed to do was to combine the code coverage reports from our unit tests with the report that Cypress generated.

To do this, I had to make some minor adjustments on our Jest setup and add the following changes. This will save the jest's code coverage report on a folder called jest-coverage for better transparency.

Code showing updates to Jest configuration to configure the reporter.
Jest configuration

I also updated the location where the Cypress code coverage report will be saved by adding the following line to our package.json file.

Code configuration to define the report directory for Cypress code coverage.
Folder configuration for Cypress code coverage

Remember to add these new folder locations to your .gitignore file so you don't commit these to your repo! Then, after following Gleb Bahmutov's instruction on his cypress-and-jest github repo, I added the following scripts on our package.json file.

Code showing additional commands on package.json to generate combined reports.
Additional commands to generate combined report

Let's look at the new commands in detail.

  • copy:reports - this creates coverage and .nyc_output folders and copies the respective json files from cypress-coverage and jest-coverage to the coverage folder.

  • combine:reports - using nyc's merge command, we are merging the two json files and then moving the merged json file to .nyc_output.

  • code:coverage:report - using nyc's report command, we are simply generating the final html report.

  • generate:code:coverage:report - this is just a handy command for running the above three commands in one go.

Here is what the final report looks like 🎉

An HTML report showing code coverage from both Jest and Cypress.
Code Coverage Report from Jest and Cypress

Wrapping Up

The Cypress code coverage plugin is a great plugin for saving the code coverage during your test runs. However, it doesn't instrument your code so you have to do this separately. The good news is if your team is using babel already, then the babel-plugin-istanbul works like a charm.

336 views4 comments