coverage-insights
v0.3.26
Published
Per-test coverage analysis for Vitest, Jest, and Gradle/JVM projects — find redundant tests, fragile lines, and coverage gaps.
Downloads
2,601
Maintainers
Readme
coverage-insights
Per-test coverage analysis for Vitest, Jest, and Gradle/JVM projects — find redundant tests, fragile lines, and coverage gaps.
Runs your test suite once per test file, collects per-test line coverage, and cross-references it to surface actionable findings.
Installation
# Run once with npx
npx coverage-insights
# Or install globally
npm install -g coverage-insightsRequires Node.js 18+. Vitest or Jest must be installed in JS/TS projects. For Gradle projects, a JDK and Gradle wrapper (gradlew) are required.
Usage
Run from your project root:
coverage-insights [options]Options
| Flag | Default | Description |
|------|---------|-------------|
| --root=<path> | cwd | Project root to analyse |
| --out=<path> | coverage-insights/ | Output directory for JSON and HTML report |
| --no-html | — | Skip generating the HTML report |
| --threshold=<0-1> | 0.9 | Jaccard similarity threshold for high-overlap pairs |
| --low-coverage=<0-100> | 80 | Line coverage % below which a file is flagged |
| --top=<n> | all | Limit each section to top N findings |
| --file=<glob> | all | Only run tests matching this pattern |
| --config=<path> | auto | Path to vitest/jest config file |
| --runner=vitest\|jest\|gradle | auto | Force a specific runner (otherwise auto-detected) |
| --concurrency=<n> | auto | Max parallel test runs |
| --integration | off | Include integration tests (Gradle only; classes named *IT, *IntegrationTest, etc. are skipped by default) |
Examples
# Basic run (HTML report generated by default)
coverage-insights
# Analyse a specific subdirectory
coverage-insights --root=./packages/my-package
# Only run tests matching a pattern
coverage-insights --file="src/auth/**"
# Limit output to top 20 findings per section
coverage-insights --top=20
# Skip HTML report
coverage-insights --no-htmlGradle / JVM projects
coverage-insights auto-detects Gradle projects by looking for build.gradle.kts or build.gradle in the project root. JaCoCo is used for coverage — if it is not already configured in your build, the runner injects it automatically via a Gradle init script.
# Auto-detected from build.gradle.kts
coverage-insights
# Force Gradle runner explicitly
coverage-insights --runner=gradle
# Limit to a specific module (substring match on module path)
coverage-insights --runner=gradle --file=applicationRequirements:
- JDK on
PATH(JAVA_HOMEset) - Gradle wrapper (
./gradlew) in the project root, orgradleonPATH - Multi-module projects:
settings.gradle.ktsorsettings.gradlewithinclude(...)entries
Standard Gradle projects (JUnit 5 / KoTest)
Supported out of the box. Tests are discovered and run in isolation one at a time, each in its own Gradle invocation. JaCoCo coverage is collected per test and aggregated at the end.
Supported test engines: JUnit 5 (Jupiter) and KoTest.
Play Framework projects (JUnit 4)
Play Framework projects use JUnit 4 and have a different source layout (app/ rather than src/main/java/). Both are handled automatically.
Because Play Framework's heavy classloading makes repeated per-test JVM startups impractical, coverage-insights uses batch mode: a single Gradle invocation runs all tests and a JUnit 4 RunListener dumps per-test JaCoCo exec data after each test case. The results are then converted to per-test JSON coverage files without spawning additional JVMs.
On the first run, a small listener JAR is compiled from bundled Java source and cached at ~/.coverage-insights/listener.jar. Subsequent runs reuse the cached JAR (invalidated by SHA-256 hash if the source changes).
Note: If your project overrides
jacocoClasspath(e.g. to pin a specific JaCoCo version), the standardjacocoAntGradle configuration may be empty.coverage-insightsfalls back to resolving JaCoCo jars from the buildscript classpath automatically.
Known limitations specific to batch mode:
- JUnit 4 only — JUnit 5 / KoTest tests will not produce per-test output in batch mode
- In multi-module projects, each subproject's batch conversion only sees that subproject's own compiled classes
General known limitations
- Maven is not supported (Gradle only)
- Branch coverage is not reported — JaCoCo's bytecode-level branch model doesn't map to the Istanbul format used internally
- The
--fileflag filters by module name substring, not a file glob (e.g.--file=applicationruns only the:applicationmodule)
Output
Results are written to coverage-insights/ (or your --out path):
report.html— interactive HTML reporttest-line-map.json— raw per-test line coverage data, keyed by"<file> > <test name>"coverage-summary.json— aggregate coverage summary (line %, function %, per file)
Report sections
| Section | What it shows |
|---------|--------------|
| Consolidation candidates | Tests in the same describe block with identical line coverage — candidates for it.each or merged assertions |
| High-overlap pairs | Test pairs sharing a high proportion of covered lines — one may be redundant |
| Zero-contribution tests | Tests whose every covered line is also covered by a single larger test |
| Hot lines | Source lines covered by an unusually high number of tests |
| Fragile lines | Source lines covered by exactly one test |
| Uncovered functions | Functions never called during the test run |
| Low coverage files | Source files below the line coverage threshold |
Licence
MIT
