Goal
Run yarn:isolate:coverage
, select a file, and see the coverage for that file only.
Introduction
When you run jest --coverage
, Jest will collect coverage for the entire project. However, you might want to focus on specific files or modules to get a more isolated view of the code coverage.
This is particularly useful when you are working on a specific feature or module and want to see the coverage for that part of the codebase without running all the tests, all the time.
Step 1: Update Jest Configuration
We need to accomodate our Jest configuration to change the collectCoverageFrom
value based on an environment variable.
// jest.config.js
import type { Config } from "jest";
const coverageFrom: string[] = [
"**/*.{ts,tsx}",
"!**/node_modules/**",
"!**/vendor/**",
];
const { COVERAGE_PATH } = process.env;
const coverageCollection = COVERAGE_PATH ? COVERAGE_PATH : coverageFrom;
const config: Config = {
collectCoverageFrom: coverageCollection,
// Rest of the Jest configuration
};
export default config;
Which you would then run in your terminal with:
$ COVERAGE_PATH=path/to/your/file/hello.ts jest --coverage path/to/your/file/hello.spec --watch
This is a bit cumbersome, and time consuming so let's improve the process.
The ideal situation would be to run a command like yarn:isolate:coverage
, select a file in a list, and see the coverage for that file only.
Step 2: Create a Script to Simplify the Process
Inside your script folder (assuming you have a script folder), create a file called isolate-coverage.sh
and add the following script:
ℹ️ Note: I have added a few comments to explain the script.
#!/bin/bash
# Finds source files (not spec files), with various extensions and select one
function select_file() {
find . \( -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" \) ! \( -name "*.spec.js" -o -name "*.spec.ts" -o -name "*.spec.jsx" -o -name "*.spec.tsx" \) | fzf --prompt="Select a source file: "
}
# Determines the corresponding test file(s) based on glob pattern
function get_test_files() {
local base_name="${1%.*}" # Remove extension
echo "$base_name.spec.*"
}
# Handles multiple test files and select one if multiple are found
function select_test_file() {
local test_files_glob=$(get_test_files "$1")
local test_files=( $test_files_glob )
if [ ${#test_files[@]} -eq 0 ]; then
echo "No test files found for $1"
exit 1
elif [ ${#test_files[@]} -eq 1 ]; then
echo "${test_files[0]}"
else
# If multiple test files exist, use fzf to select one
echo "${test_files[@]}" | tr ' ' '\n' | fzf --prompt="Multiple test files found. Select one: "
fi
}
# Validate input argument for the type of test to run
if [ "$#" -eq 0 ]; then
echo "No arguments provided. Use --coverage or --unit."
exit 1
fi
# Determines the test command directly
case "$1" in
--coverage)
command_prefix="COVERAGE_PATH="
test_command="jest --coverage"
;;
--unit)
command_prefix=""
test_command="jest"
;;
*)
echo "Invalid argument provided. Use --coverage or --unit."
exit 1
;;
esac
# Execute the file selection process
selected_file=$(select_file)
if [ -z "$selected_file" ]; then
echo "No file selected."
exit 1
fi
# Determine the corresponding test file
test_file=$(select_test_file "$selected_file")
if [ -z "$test_file" ]; then
echo "No test file selected or found."
exit 1
fi
# Run Jest directly with the selected test file, including the coverage path if necessary
if [[ "$1" == "--coverage" ]]; then
COVERAGE_PATH="$selected_file" $test_command "$test_file" --watch
else
$test_command "$test_file" --watch
fi
Step 3: Assign the right permissions
Make the script executable by running:
$ chmod +x scripts/isolate-coverage.sh
Step 4: Add the Script to Your package.json
Add the following script to your package.json
:
{
"scripts": {
"test:isolate:coverage": "scripts/isolate-coverage.sh --coverage",
"test:isolate:unit": "scripts/isolate-coverage.sh --unit"
}
}
Step 5: Install fzf
You need to install fzf
to use the script. You can install it with brew
:
$ brew install fzf
Step 6: Run the Script
Now you can run the script with:
$ yarn test:isolate:coverage
You will be prompted to select a file, and the script will run Jest with the coverage for that file only.
Conclusion
Facilitate your and your team's life by making their developer's experience better. Do not underestimate the power of small improvements in your workflow.
The biggest mountains are made of small stones