Combining Jest and Cypress code coverage reports in your Angular app

Shafiq Jetha
4 min readJul 31, 2021

--

Photo by Isaac Smith on Unsplash

When writing front-end tests, code coverage is an important metric that helps you determine how many critical paths of your application are covered.

Cypress has their own tutorial and example repo which uses Babel, but in this post I’ll go through the process of doing this with an Angular application, without using Babel.

Instrumenting and reporting

Codecov has a feature whereby any code coverage metrics that are uploaded with the same branch name will be merged into one report. This is a useful feature if you have several different test runners and need them all to be combined into one report. For producing coverage reports for Jest and Cypress some features need to be added and enabled.

Jest comes with the istanbul instrumenter and coverage reporting tool built-in, and since this is now the standard for instrumenting code, this is a useful feature. To use it, you have to run jest with the --coverage flag added. If you already have this in your package.json file, you can make the following modification:

- "test": "ng test"
+ "test": "ng test -- --coverage"

This will produce a coverage report for your Jest tests, but this isn’t enough. We also need Jest to collect coverage for all of the files that have no test. In your jest.config.js file, you will need to make this modification:

+ rootDirs: ['<rootDir>/src'],
+ collectCoverage: true,
- coverageReporters: ['json', 'html'],
+ coverageReporters: ['lcov'],
+ collectCoverageFrom: ['**/*.ts'],
+ coverageDirectory: './coverage/jest',

This will create an lcov format coverage report, but will also give us a proper understanding of what is and isn’t covered across our entire application.

We’re also going to put out output in a separate directory so that when we run our Cypress tests, our Jest coverage report doesn’t get overwritten.

To get Cypress set up there are a few more steps involved. As mentioned in the readme on skylock/cypress-angular-coverage-example because the Cypress package doesn’t do instrumenting, we have to add the @cypress/code-coverage package and modify the build process. This will trigger instrumenting on our code so that we can produce a coverage report. This package uses Istanbul’s successor nyc, and as such a second step is required for us to generate an lcov format report. We also need to modify the webpack config for the development build so that the code gets instrumented correctly.

Begin by adding the @cypress/code-coverage package:

npm i -D @cypress/code-coverage

Then add the package to Cypress’ support/index.ts file:

+ import '@cypress/code-coverage/support

Now that we have Cypress set up, we can move onto modifying the build process. We achieve this by using the ngx-build-plus package which can be installed with the following command:

npm i -D @ngx-build-plus

In the cypress folder, a coverage.webpack.js needs to be added with the following content:

module.exports = {
module: {
rules: [
{
test: /\.(js|ts)$/,
loader: 'istanbul-instrumenter-loader',
options: { esModules: true },
enforce: 'post',
include: require('path').join(__dirname, '..', 'src'),
exclude: [/\.(e2e|spec)\.ts$/, /node_modules/, /(ngfactory|ngstyle)\.js/],
},
],
},
};

This will allow us to instrument our code, but we also need to modify our angular.json file to use this webpack file:

- "builder": "@angular-devkit/build-angular:dev-server",
+ "builder": "ngx-build-plus:dev-server",
+ "options": { "browserTarget": "ng-new-app:build", "extraWebpackConfig": "./cypress/coverage.webpack.js" }

Now we can test our project by running

ng e2e

or

npm run <project>:cypress-run

Once the test run has completed, you still need to covert the nyc output to lcov so that you can proceed with the next step. You can achieve this by running this command:

npx nyc report --reporter=lcov

This will transform your nyc output into lcov output, so that both reports are in the same format. You can now decide how you wish to track your code coverage.

Option 1: Codecov

When you upload multiple reports, Codecov will merge these reports together, so simply uploading the coverage directory’s content will combine these results and produce an accurate coverage report.

If you are using GitHub Actions, uploading the files is as simple as calling the relevant Action:

uses: codecov/codecov-action@v1

Once it is uploaded, you will get access to Codecov’s different coverage diagrams as well as a histogram of your coverage over time.

Coverage over time for an example project

Option 2: Manually merge the reports

If you simply want to manually merge the reports and feed them into your own code coverage tool, lcov reports can be appended to one another and still retain the same detail. After installing the lcov package in Ubuntu, you can generate a HTML report of the combined coverage by running the following command:

genhtml --prefix <directory> lcov.info --output-directory=./cov
An example of the genhtml output

If you’d like to have a ready-to-go project that has all of this included, and more, check out this project I helped out with: sardapv/angular-material-starter-template

Now go forth, and cover!

--

--

Shafiq Jetha
Shafiq Jetha

Written by Shafiq Jetha

A senior developer obsessed with a fast development inner loop