Skip to content

Commit 4ec5ba8

Browse files
committed
chore(ai): add testing-gaps skill
1 parent 5a14a28 commit 4ec5ba8

1 file changed

Lines changed: 99 additions & 0 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
name: testing-gaps
3+
description: Run coverage, inspect results, and identify missing test scenarios for a given source file. Use when analysing test coverage or finding untested branches.
4+
---
5+
6+
# Testing Gaps
7+
8+
Find untested branches and missing real-world test scenarios for a source file.
9+
10+
## Workflow
11+
12+
1. **Run text coverage** for the target file
13+
2. **Identify uncovered branches** from the output
14+
3. **Cross-reference** with test file to understand what's tested
15+
4. **Report** uncovered branches + missing real-world scenarios
16+
17+
## Step 1: Run Coverage
18+
19+
Use `cargo llvm-cov` with `--text` output (not `--html`) for parseable results.
20+
21+
```bash
22+
# Full coverage, filtered to target file
23+
cargo llvm-cov test --text \
24+
--ignore-run-fail \
25+
--ignore-filename-regex '(_test.rs|\/test\/)' \
26+
2>/dev/null | sed -n '/TARGET_FILE\.rs:/,/^$/p'
27+
```
28+
29+
Example for `preferred_semver.rs`:
30+
31+
```bash
32+
cargo llvm-cov test --text \
33+
--ignore-run-fail \
34+
--ignore-filename-regex '(_test.rs|\/test\/)' \
35+
2>/dev/null | sed -n '/preferred_semver\.rs:/,/^$/p'
36+
```
37+
38+
## Step 2: Read Coverage Output
39+
40+
The text format shows per-line execution counts:
41+
42+
```
43+
42| 80| .and_then(|range| ...) # Hit 80 times
44+
74| 0| Some(preferred) # Never hit
45+
321| 0| instance.mark_conflict(...) # Never hit
46+
```
47+
48+
- `count > 0` = covered
49+
- `count = 0` = uncovered branch
50+
- `^N` annotations on sub-expressions show partial coverage within a line
51+
52+
### Extract only uncovered lines
53+
54+
```bash
55+
... | grep -E '^\s+\d+\|\s+0\|'
56+
```
57+
58+
## Step 3: Classify Gaps
59+
60+
For each uncovered branch, determine:
61+
62+
1. **What code path leads here?** — Trace the `if/else` chain backward
63+
2. **What input would trigger it?** — What package.json + config combination
64+
3. **Is it reachable?** — Some branches may be defensive/unreachable
65+
4. **Is it worth testing?** — Real-world scenario vs theoretical edge case
66+
67+
### Categories
68+
69+
| Category | Action |
70+
| -------------------------------- | ----------------- |
71+
| Real-world scenario never tested | Write a test |
72+
| Edge case in existing logic | Write a test |
73+
| Defensive branch (unreachable) | Note but skip |
74+
| Dead code | Consider removing |
75+
76+
## Step 4: Identify Missing Scenarios
77+
78+
Beyond line coverage, look for missing _combinations_:
79+
80+
- Feature A tested, Feature B tested, A+B never tested together
81+
- Only tested with one package, never with multiple
82+
- Only tested with `highestSemver`, never `lowestSemver`
83+
- Only tested with one range type (`^`), never others (`>=`, `<=`)
84+
- Only tested without semver groups, never with
85+
86+
## Step 5: Report
87+
88+
Structure findings as:
89+
90+
1. **Uncovered branches** — Specific lines, what triggers them, why untested
91+
2. **Missing real-world scenarios** — Combinations and interactions not covered
92+
93+
## Running Tests After Adding Coverage
94+
95+
```bash
96+
just test # All tests
97+
cargo test test_name -- --nocapture # Specific test
98+
just coverage # Regenerate coverage report
99+
```

0 commit comments

Comments
 (0)