Jest: How to merge coverage reports from different jest test runs - jestjs

Has anyone managed to combine test coverage report from two separate jest test runs?
I am newbie trying to use the default jest coverage reporters: ["json", "lcov", "text", "clover"]
I have tried using nyc to combine coverage-final*.json files from tmp folder and output to a full-test-coverage/ folder.
npx nyc report --report-dir=full-test-coverage/ --reporter=html -t tmp
The full-test-coverage folder is created with index.html etc. However, the combined report is empty.

I managed to get it working with nyc. Steps:
Collect multiple coverage reports using coverage reporter "json"
Put them all in one directory (which in my case required renaming multiple coverage-final.json files)
nyc merge multiple-sources-dir merged-output/merged-coverage.json
nyc report -t merged-output --report-dir merged-report --reporter=html --reporter=cobertura

I was struggling with this too but I managed to do it by using the istanbul-merge package
So assuming that you want to merge two test coverage named coverage-final.json located in two different folders f1 and f2,and name the output f3/coverage.json you can do :
npx istanbul-merge --out coverage.json ./f1/coverage-final.json ./f2/coverage-final.json
and then use instanbul to create the HTML report :
npx istanbul report --include coverage.json --dir f3 html

Building off of another answer, here is a script that will collect all the coverage files from multiple yarn workspaces and merge them:
#! /bin/bash
set -e
rm -rf coverage
mkdir -p coverage/workspaces
yarn workspaces foreach -Apv exec bash -c '[ ! -f coverage/coverage-final.json ] && exit 0 || cp coverage/coverage-final.json '$(pwd)'/coverage/workspaces/$(basename $(pwd))-coverage-final.json'
yarn run nyc merge coverage/workspaces coverage/monorepo-coverage.json
yarn run nyc report -t coverage --report-dir coverage/html --reporter=html-spa
Note that the $(pwd) executes in the script's context (I close and re-open the single quotes around that command) while the other subshells are quoted and will occur in the context of the workspace exec (and so have a CWD of the workspace.

To merge, I usually use nyc with --no-clean option, like this:
{
"cover": "npm run cover:unit && npm run cover:integration && npm run cover:report",
"cover:unit": "nyc --silent npm run test:unit",
"cover:integration": "nyc --silent --no-clean npm run test:integration",
"cover:report": "nyc report --reporter=text-lcov > coverage.lcov",
}

Related

How to stop a commit if test coverage is below a certain percentage?

I'm using Jest to test a NestJS application and I'm trying to create a git hook with husky that will not allow a commit if tests coverage are under 95%, I haven't tried anything yet cause I really don't know how to even describe my question properly.
But just to be more clear, what I need is a git hook just like this:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run format
npm run lint
npm run test
git add -u
create a git hook with husky that will not allow a commit if tests coverage are under 95%
It seems you already have a test hook on husky, and if that npm run test is using Jest as I'm assuming it does, all you need to do is add a Jests configuration to your package.json.
Open package.json and search for a property like:
"jest": {
That's where you put your Jest configuration parameters.
Just add the following properties to it:
"collectCoverage": true,
"coverageThreshold": {
"global": {
"lines": 95
}
}
You're going to want to change lines property value to whatever percentage you want.
As a side note, I'm pretty sure this is default Jest configuration, but you also need to select the folders and files you want to run test coverage analysis on, since you already have a test hook you probably already have this, but just to make sure:
"collectCoverageFrom": [
"./src/**/*.(t|j)s"
],
This will run a coverage test on every file, .JS or .TS, inside /src directory.
Now whenever you commit something, or try to run npm run test, it will also run test coverage and block commit if it's below the selected value.

Why does nyc does not gather test coverage for my project?

I am developing an extension for vscode using typescript. I set up a GitHub Action which is executing my test cases. To gather the test coverage I am using nyc.
These are my node scripts:
"compile": "tsc -p ./",
"test": "npm run compile && node ./out/test/runTest.js",
"coverage": "nyc npm run test"
When I run npm run coverage I see all my test cases are getting executed (they are not stored in the file runTest.js), but only the coverage for the test file runTest.js is gathered. The relevant classes lib.ts and extension.ts are not shown in the coverage.
Why is this so? What am I doing wrong?
See my package.json and .nycrc.json for configuration.
I could fix this problem by sticking to the great blogpost which I found posted on a similar Question.
The problem is, that NYC is a command line tool. When executing the test I focused on my configuration in the .nycrc file. Fact is, that the visual studio code test runner is not using this configuration and has to be configured inside the test runner.
I fixed the broken test coverage generation inside this commit.

How to watch .sss files and re-run my npm script if they change

Is there a way to watch my .sss files and re-run this if they change?
"css": "postcss -u autoprefixer -u postcss-easy-import -p sugarss src/index.sss -o src/index.css"
I can't find a way, I've looked on the net all over. I don't see any kind of watch available from postcss. There's a -w or --watch with the postcss-cli but I tried adding that to the end of the script above. Unless I'm just doing it wrong, my css script does not re-run itself if my .sss files change.
maybe there's some generic node watcher lib I can use?
nodemon is a very powerful tool to re-run your scripts based on any change in your files , default file extension for nodemon to watch is .js and default script to run from your package.json file is start script.
You can overwrite watched extension using -e option , then extensions separated by , for example -e sss in your case.
Also you can overwrite the script you want to run using --exec option and then pass the script you want to run , in your case it will be --exec "npm run css"
And put all together nodemon -e sss --exec "npm run css" , this will watch changes in sss files and run css script

mocha not running all tests in test dir

This is my folder structure
src/
a.js
b.js
test/
a.spec.js
b.spec.js
and I've tried running
~/.../src $ mocha
~/.../src $ mocha test
~/.../src $ mocha test/
~/.../src $ mocha ./test/
~/.../src $ mocha ./test/*.js
but non worked... all I get is just one test file running and the rest are ignored.
The docs say that (1) should do the job but well it doesn't.
Well... I'm an idiot. I had it.only in one of my files and I forgot it. Removing the .only was the answer. All the test files are running now.
Sorry for that, shame on me...
It's built like this so you can run your test suite on just a file or two if you're doing development on them. If you want to run mocha throughout your project just specify --recursive
You can see some documentation here.
Better yet, you can just specify it in your package.json for CD. First do npm install mocha --save-dev and then put this in your package.json file then run npm test
{
"scripts": {
"test": "./node_modules/.bin/mocha --recursive",
}
}
Create a moch.opts file under test directory and add recursive option
--recursive
Run ~/.../src $ mocha command; it should work.

How to make Istanbul generate coverage for all of my source code?

Currently Istanbul is only generating coverage for files that are used in my tests, which is okay, but seems to defeat the purpose of having coverage somewhat.
I have no Istanbul configuration, and am invoking it via npm test with the following script string:
$ istanbul cover _mocha -- -R dot --check-leaks --recursive test/
Is there a way to generate coverage for all of my source code?
Found the answer, I think I'm partly lucky that the directory structure I have chosen allows me to use this option, but my test command is now:
$ istanbul --include-all-sources cover _mocha -- -R dot --recursive test/
The --include-all-sources is the important part.
Istanbul recommends using nyc in order to check code coverage. It suggests an approach like this:
nyc mocha
After running this command, we'll get the coverage report. But there is a couple of pitfalls.
First of all, by default mocha is looking for tests in folder test. In order to override it, we have to set our own path in file mocha.opts like this:
nyc mocha --opts ./mocha.opts
And mocha.opts contains such code, for example:
spec/unit/back-end/**/*.spec.js
Another problem is that by default nyc checks coverage of only required files, that is your question is about. The solution is to set two options for nyc (I run test as an npm script so I set options in package.json). Here is the code:
"nyc": {
"all": true,
"include": [
"routes/*.js",
"routes/**/*.js",
"models/*.js"
]
},
"scripts": {
"mocha": "nyc mocha --opts ./mocha.opts",
}
Another way to achieve it is to set not include, but exclude option in order to exclude from coverage checking inappropriate files. It's strange, but the sole option all doesn't work, it requires include or exclude options. You can get more info about nyc options via nyc --help.
P.S. I don't know nyc and mocha deeply and I'm only based on my own experience.
For generating coverage for all files, have the following in your package.json
"istanbulCoverage": "nyc --reporter=lcov --reporter=text-lcov --all -x
\"./node_modules/\" -x \"./coverage/\" check-coverage --functions 90 npm run test"
Here --all flag fetches all the files in your project. If u want to exclude specific files or folders, you can use -x option.
Apart from this, if you want to specify coverage rate for you application, then use check-coverage option to specify the threshold. In my case, I've specified functions to have a coverage threshold of 90%. Otherwise, the coverage report generation fails.(i am running my karma test after coverage report generation).
Hope this helped:)
In my case, --include-all-sources did not work for me. Files that were not require-d were still excluded from the final coverage report.
Eventually, I came across this issue on the istanbul GitHub where the maintainer stated:
Yes, that is expected behavior. istanbul works by hooking require so if a file is never require-d it is as if it doesn't exist.
The only fool-proof solution that I found was to manually require all files that I wanted to include in my coverage report. I create the file include-all.test.js alongside my other test scripts and added the following bit of code:
var glob = require( 'glob' )
var path = require( 'path' );
glob.sync( './path/to/js/code/*.js' ).forEach( function( file ) {
// we don't care about errors here, we just want to require the file
try {
require( path.resolve( file ) );
} catch(e) {}
});
This will absolutely ensure that your untested files are included in the istanbul coverage report.

Resources