You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Find unit tests whose coverage is fully subsumed by integration tests.
12
-
13
3
Find the unit tests your AI agent wrote twice.
14
4
15
5
## Overview
16
6
17
-
`ovelapped`analyzes your test suite to find unit tests that don't cover anything your integration tests don't already cover. It runs each unit test in isolation, compares its coverage fingerprint against a reference suite (e.g. integration or e2e tests), and reports which tests are redundant.
7
+
`ovelapped`finds unit tests that add no coverage beyond a reference suite, such as integration, e2e, or provider tests.
18
8
19
-
Supports **vitest** and **jest** out of the box — the runner is auto-detected from your project dependencies.
9
+
It runs each candidate unit test in isolation, compares its statement and branch coverage against the reference coverage, and reports tests that cover nothing new.
20
10
21
-
Use it when a test suite has grown in bulk, especially after AI-assisted test generation, and you want to keep only the tests that add coverage signal.
11
+
Use it when a test suite has grown in bulk, especially after AI-assisted test generation, and you want to keep the tests that still carry signal.
12
+
13
+
Supports **vitest** and **jest** out of the box. The runner is auto-detected from your project dependencies.
22
14
23
15
## Real-World Cleanup
24
16
25
-
In [callstackincubator/agent-device#595](https://github.com/callstackincubator/agent-device/pull/595), `ovelapped`was used to audit a large AI-assisted test suite against provider-integration coverage.
17
+
In [callstackincubator/agent-device#595](https://github.com/callstackincubator/agent-device/pull/595), `ovelapped`audited a large AI-assisted unit suite against provider-integration coverage.
26
18
27
19
| Metric | Before | After |
28
20
|---|---:|---:|
@@ -35,31 +27,36 @@ In [callstackincubator/agent-device#595](https://github.com/callstackincubator/a
35
27
| Branch coverage | 71.94% | 71.96% |
36
28
| Line coverage | 84.49% | 84.5% |
37
29
38
-
The important bit: all removed tests covered only statements and branches already covered by integration tests. The suite got smaller without losing coverage.
30
+
Every removed test covered only statements and branches that the integration suite already covered. Smaller suite, same coverage signal.
39
31
40
32
## Quick Start
41
33
42
-
Compare default unit tests against a reference suite:
34
+
Compare a unit suite against the suite that already gives you confidence:
43
35
44
36
```bash
45
-
npx ovelapped analyze
37
+
npx ovelapped analyze \
38
+
--reference integration \
39
+
--unit unit \
40
+
--include "src/**/*.test.ts"
46
41
```
47
42
48
-
This will:
43
+
Review `ovelapped-report.json`, then preview removals:
49
44
50
-
1. Run your reference test suite with coverage
51
-
2. Discover and run each unit test in isolation
52
-
3. Compare coverage fingerprints at statement and branch level
53
-
4. Write a JSON report to `ovelapped-report.json`
45
+
```bash
46
+
npx ovelapped prune --dry-run
47
+
```
54
48
55
-
To remove the redundant tests:
49
+
Apply the cleanup when the preview looks right:
56
50
57
51
```bash
58
-
npx ovelapped prune --dry-run # preview changes
59
-
npx ovelapped prune # apply changes
52
+
npx ovelapped prune
60
53
```
61
54
62
-
For a Vitest workspace with named projects, like the agent-device cleanup:
55
+
Then run your full test suite with coverage and confirm thresholds still pass.
56
+
57
+
## Common Setups
58
+
59
+
Vitest workspace with named projects, like the agent-device cleanup:
63
60
64
61
```bash
65
62
npx ovelapped analyze \
@@ -69,13 +66,12 @@ npx ovelapped analyze \
69
66
--include "src/**/*.test.ts"
70
67
```
71
68
72
-
Recommended cleanup loop:
69
+
Existing reference coverage:
73
70
74
-
1. Run `ovelapped analyze`.
75
-
2. Review `ovelapped-report.json`.
76
-
3. Run `ovelapped prune --dry-run`.
77
-
4. Apply with `ovelapped prune`.
78
-
5. Run your full test suite with coverage and confirm thresholds still pass.
Runs the full analysis. By default it executes your reference suite to generate coverage, then runs each discovered unit test individually.
91
-
92
-
Use `--reference` for the integration, e2e, or provider suite that should act as the coverage baseline. Use `--unit` for the suite containing candidate tests to remove.
93
-
94
-
If you already have a `coverage-final.json` from a prior run, skip the reference suite:
Builds the redundancy report. Use `--reference` for the suite that acts as the coverage baseline, and `--unit` for the suite containing candidate tests to remove.
99
87
100
88
### `ovelapped prune`
101
89
102
-
Reads the analysis report and removes subsumed tests from source files. Files where all tests are subsumed are deleted entirely; files with a mix get individual test blocks removed.
90
+
Reads the report and removes redundant tests. Files where every test is redundant are deleted entirely; mixed files get individual test blocks removed.
103
91
104
92
Always review changes with `--dry-run` first.
105
93
@@ -118,10 +106,11 @@ Always review changes with `--dry-run` first.
118
106
119
107
## How It Works
120
108
121
-
1.**Reference fingerprint** — Runs (or loads) coverage for the reference suite. Each covered statement and branch becomes a key in a `Set<string>` (e.g. `"/src/foo.ts:s:3"`, `"/src/foo.ts:b:1:0"`).
122
-
2.**Per-test fingerprint** — Runs each unit test in isolation with coverage, building the same fingerprint.
123
-
3.**Subsumption check** — If every key in a test's fingerprint exists in the reference fingerprint, the test is *subsumed* — it exercises no code path that the reference suite doesn't already cover.
124
-
4.**Pruning** — Removes subsumed test blocks from source files using bracket-matching (no AST required).
109
+
1. Runs or loads Istanbul `coverage-final.json` for the reference suite.
110
+
2. Runs each candidate unit test in isolation with coverage.
111
+
3. Turns covered statements and branches into fingerprint keys, such as `"/src/foo.ts:s:3"` and `"/src/foo.ts:b:1:0"`.
112
+
4. Marks a test redundant only when every key in its fingerprint already exists in the reference fingerprint.
113
+
5. Removes redundant test blocks with bracket matching. No AST, no runtime dependencies, no guesswork.
0 commit comments