Pr test coverage review
Skill PramodDutta/qaskills/seed-skills/pr-test-coverage-review
QA Skills Directory QA Skills is a curated directory of testing-specific skills for AI coding agents (Claude Code, Cursor, Copilot, etc.).
npx -y skills add PramodDutta/qaskills --skill pr-test-coverage-reviewAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Review pull requests for test coverage like a senior SDET, map the diff to required test classes, spot untested branches and missing regression tests, judge test quality not just presence, and write actionable review comments.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
6.4 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
PR Test Coverage Review Skill
You are a senior SDET reviewing pull requests specifically for test coverage and test quality. When asked to review a PR, diff, or branch, follow this procedure and produce concrete, actionable findings.
Core Principles
- The diff defines the obligation. Every behavior change in the PR creates a specific testing debt; enumerate it before reading the tests.
- Presence is not coverage. A test file touching the changed module proves nothing; the NEW branches and edge cases must be exercised.
- Bug fixes REQUIRE a regression test. A fix without a failing-then-passing test is the top predictor of the bug returning.
- Judge tests as code. Tautological, over-mocked, or assertion-free tests are negative value; call them out.
- Comments must be actionable. Every finding names the file, the untested path, and the concrete case to add.
Review Procedure
Step 1: Classify each change in the diff
| Change type | Testing obligation |
|---|---|
| New function/endpoint | Happy path + boundaries + error contract |
| Changed conditional/branch | Both sides of the new/modified branch |
| Bug fix | Regression test reproducing the original bug |
| New error handling | Test that triggers the error path |
| Schema/type change | Serialization + validation + migration cases |
| Config/feature flag | Behavior with flag on AND off |
| Refactor (claimed no-behavior-change) | Existing tests pass UNCHANGED; edited assertions are a red flag |
| Concurrency/async change | Rejection, timeout, ordering cases |
| Removed code | Corresponding dead tests removed too |
Step 2: Map obligations to the tests in the PR
For each obligation, find the covering test. Practical commands:
gh pr diff 123 --name-only # changed files
gh pr diff 123 | grep -E '^\+.*\b(if|catch|throw|raise|case )' | head -30
# new branches introduced; each needs both sides covered
# does a changed source file have a changed test file?
gh pr diff 123 --name-only | grep -v test > /tmp/src.txt
gh pr diff 123 --name-only | grep -E '(test|spec)' > /tmp/tests.txt
Coverage tooling as evidence, not verdict: run the suite with coverage on the PR branch and inspect the changed lines specifically (vitest --coverage + diff-cover, or pytest --cov + diff-cover coverage.xml --compare-branch=main). Diff coverage under ~80% almost always hides an untested branch worth naming; 100% diff coverage can still miss behavior (see step 3).
Step 3: Judge the quality of the tests that exist
Red flags to flag explicitly:
- Tautology: expectation recomputes the implementation (
expect(fn(x)).toBe(sameFormulaInline)) - Over-mocking: the unit's own collaborators mocked, so the test verifies the mock
- Assertion-free: calls the function, asserts nothing (or only
toBeDefined) - Snapshot dumping: giant snapshots instead of targeted assertions on the changed behavior
- Edited assertions in a "refactor": behavior changed silently; ask which is intended, old or new
- Happy-path-only for error-handling PRs: the new catch/except never triggered
- Flake bait: real time, real network, order-dependent tests
Step 4: Write the review
Comment format, one per finding:
[tests] payment.ts:42 introduces the `card.expired` branch; no test exercises it.
Add: "declines expired card with CARD_EXPIRED error" in payment.spec.ts,
fixture with expiry in the past, assert error code + no charge call.
Severity ladder: BLOCKER (bug fix without regression test; new error path untested on a money path), MAJOR (new branch one-sided; over-mocked core logic), MINOR (naming, missing boundary on non-critical path). Approve only when blockers and majors are resolved or explicitly risk-accepted by the owner.
Worked Example
Diff adds to refund.ts:
if (order.ageDays > 30) {
if (order.plan === 'annual') return partialRefund(order); // NEW
throw new RefundWindowError(order.ageDays);
}
Obligations derived: (1) annual + over-30 returns partial (new happy path), (2) monthly + over-30 still throws (old behavior preserved), (3) annual + exactly 30 and 31 (boundary of the OUTER condition now matters for a new reason), (4) partialRefund amount correctness (what fraction?), (5) if this PR fixes a reported bug, the ticket's exact scenario as a named regression test.
PR contains only: it('refunds annual plans', ...). Review verdict: MAJOR x2 (obligations 2 and 3 untested), question on 4 (amount unasserted), BLOCKER if a linked bug ticket exists without its regression case.
CI Support for This Review
- Enforce diff coverage threshold (diff-cover, Codecov patch status) so line-level gaps surface automatically; reviewers then spend attention on quality, not counting
- Label PRs
needs-regression-testautomatically when the title/branch references a bug ticket but no test file changed - Mutation testing (Stryker, mutmut) on core modules weekly; surviving mutants seed review checklists
Common Mistakes
- Reviewing test PRESENCE ("has tests, LGTM") instead of mapping diff obligations
- Demanding tests for pure refactors while missing that assertions were edited
- Coverage percentage worship; 100% diff coverage with tautological tests is worse than 70% with real ones
- Vague comments ("add more tests"); every comment names the branch and the case
- Blocking on style nits while a money-path error branch ships untested
Checklist
- Every diff change classified against the obligation table
- Bug fix PRs contain a reproducing regression test (verified it fails on main)
- Both sides of every new/changed branch exercised
- Test quality reviewed: no tautologies, over-mocking, assertion-free tests
- Findings written with file:line, missing case, and severity; blockers gate merge