Demo unit tests with code coverage from both Cypress and Jest
# install and run tests
$ npm it
# runs Jest and Cypress tests headlessly
# generates combined code coverage report
$ open coverage/lcov-report/index.htmlThe application source code is just a single file src/calc.js. Let's cover this file with unit tests by using two test runners: Jest and Cypress.
The Jest setting were initialized using npx jest --init command:
In the generated jest.config.js enable code coverage collection, and output into folder jest-coverage (to avoid clashing with Cypress coverage report).
// jest.config.js
module.exports = {
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,
// The directory where Jest should output its coverage files
coverageDirectory: 'jest-coverage',
// The test environment that will be used for testing
testEnvironment: 'node'
}The Jest unit tests are in the file tests/calc.test.js and the tests only run the add function. We can run the Jest tests and see the coverage summary.
The coverage reports in jest-coverage folder by default include JSON, LCOV and static HTML reports. The HTML report shows that the function sub was not reached by the Jest tests.
First install Cypress
$ npm install -D cypressInitialize Cypress folder with npx @bahmutov/cly init command.
In cypress/integration/spec.js let's require sub function and test it
// cypress/integration/spec.js
const { sub } = require('../../src/calc')
it('subtracts 10 - 5', () => {
expect(sub(10, 5)).to.equal(5)
})The test passes
Code coverage in Cypress is done via @cypress/code-coverage plugin. I suggest following the installation instructions in that repo.
First, install the plugin and babel-plugin-istanbul to instrument code.
npm i -D @cypress/code-coverage babel-plugin-istanbulAdd to your cypress/support/index.js file:
import '@cypress/code-coverage/support'Register tasks in your cypress/plugins/index.js file:
module.exports = (on, config) => {
require('@cypress/code-coverage/task')(on, config)
on('file:preprocessor', require('@cypress/code-coverage/use-browserify-istanbul'))
return config
}Because we saved the Jest coverage report in jest-coverage, set Cypress to save its coverage to cypress-coverage. Since nyc is used to generate the report, add nyc object to package.json file.
{
"nyc": {
"report-dir": "cypress-coverage"
}
}Run Cypress with npx cypress open and a report should be saved. As you can see, we have missed the add function!
We have two folders with coverage reports generated by Jest and Cypress.
$ ls -la *-coverage
cypress-coverage:
total 24
drwxr-xr-x 6 gleb staff 204 Jul 22 23:04 .
drwxr-xr-x 20 gleb staff 680 Jul 22 23:05 ..
-rw-r--r-- 1 gleb staff 744 Jul 22 23:05 clover.xml
-rw-r--r-- 1 gleb staff 1000 Jul 22 23:05 coverage-final.json
drwxr-xr-x 10 gleb staff 340 Jul 22 23:04 lcov-report
-rw-r--r-- 1 gleb staff 201 Jul 22 23:05 lcov.info
jest-coverage:
total 24
drwxr-xr-x 6 gleb staff 204 Jul 22 21:00 .
drwxr-xr-x 20 gleb staff 680 Jul 22 23:05 ..
-rw-r--r-- 1 gleb staff 744 Jul 22 23:05 clover.xml
-rw-r--r-- 1 gleb staff 1000 Jul 22 23:05 coverage-final.json
drwxr-xr-x 10 gleb staff 340 Jul 22 21:00 lcov-report
-rw-r--r-- 1 gleb staff 201 Jul 22 23:05 lcov.info
Let's combine the two reports and generate the final report. There is a script in package.json that does just that. It copies cypress-coverage/coverage-final.json and jest-coverage/coverage-final.json into a folder, runs nyc merge command, the creates the combined report using nyc report ... command.
$ npm run report:combined
...
coverage files in reports merged into coverage.json
> cypress-and-jest@1.0.0 report:combined /Users/gleb/git/cypress-and-jest
> nyc report --reporter lcov --report-dir coverageThe final HTML report shows that we have reached all source statements in calc.js file.
You can store the produced static HTML report on your continuous integration server. For example see .circleci/config.yml file.
- Cypress code coverage guide
- @cypress/code-coverage plugin







