Review and Slim an Overgrown Snapshot Suite
Audit snapshot sizes and update frequency, convert intent-bearing cases to explicit assertions, and keep snapshots only where structure is the contract.
Task
Reduce a snapshot suite to the cases where snapshots add value, replacing the rest with precise assertions.
When to use this
Every pull request updates 60 snapshot files that nobody reads. The suite detects nothing but formatting changes, and reviewers approve blind.
Prerequisites
- A test suite with existing snapshots, such as Jest or Vitest
- Git history to measure snapshot churn
- Time for one deliberate cleanup pass
Steps
1. Rank snapshots by size and churn.
for f in $(git ls-files "*.snap"); do echo "$(wc -c < $f) $(git log --oneline --since="3 months ago" -- $f | wc -l) $f"; done | sort -rn | head -15Expected output: A table of bytes and change-counts: big files changing often are blind-approval machines.
2. Delete snapshots that assert nothing meaningful.
npx vitest run -u 2>/dev/null; git diff --stat -- "*.snap" | tail -3Expected output: Regenerating after deletion shows which snapshots silently absorbed changes, the clearest no-value signal.
3. Convert intent-bearing cases to explicit assertions.
it("formats the invoice total", () => {
const out = renderInvoice(invoice);
expect(out.total).toBe("1,234.56 EUR");
expect(out.currency).toBe("EUR");
});
Expected output: The assertion names the contract, so a regression reads as a specific failure instead of a wall of diff.
4. Keep snapshots where structure itself is the contract.
it("renders the navigation structure", () => {
expect(Object.keys(nav).sort()).toMatchInlineSnapshot(`
Array [
"account",
"docs",
"search",
]
`);
});
Expected output: Inline snapshots live next to the test, stay small, and their diff is reviewable in the pull request itself.
5. Gate future snapshot growth in CI.
if (snapshotBytes(f) > 2000) fail("snapshot too large: use explicit assertions");Expected output: New oversized snapshots fail the build, so the suite cannot quietly regress into blind approvals again.
Troubleshooting
Problem
Team fears losing coverage by deleting snapshots
Solution
Delete one file and run the suite against last week intentional-breaking commit; if snapshots did not catch it, they were not coverage.
Problem
Snapshots churn due to nondeterministic fields
Solution
Strip timestamps and ids with serializers before snapshotting; determinism is a precondition for value, not an optional polish.
Problem
Inline snapshots fight the formatter
Solution
Configure the test framework snapshot serializers and run the same prettier config; formatting noise is the top churn source and it is fixable.
Limitations
- Snapshots capture current behavior including its bugs; converting them to assertions is the moment to decide what is intended.
- A slimmed suite shifts detection burden to explicit tests; budget time for writing them.
A snapshot nobody reads is not a test
Snapshot tests promise wide coverage at low effort, and they deliver it, until the update becomes reflexive. The audit is quantitative: measure bytes and churn per file, and the blind spots name themselves. The slimming rule is intent: when a specific property matters, assert it explicitly; keep snapshots only where the shape of the output is itself the contract, and keep them inline and small.
# Size and 3-month churn per snapshot
for f in $(git ls-files "*.snap"); do
echo "$(wc -c < $f) $(git log --oneline --since='3 months ago' -- $f | wc -l) $f"
done | sort -rn | head -15
Churn is the honesty metric
A snapshot that changes in every third pull request is not protecting anything; it is collecting diff noise. A snapshot that has not changed in a year is either protecting a genuinely stable contract or protecting nothing at all. The way to tell is deletion plus a deliberate breaking change: if the suite still passes, the snapshot was decoration.
Explicit assertions age into documentation
The difference between a snapshot and an assertion is that an assertion states intent. Six months later, a failed assertion tells you what broke; a failed snapshot tells you something differs. Converting the intent-bearing cases is where the cleanup pays its cost back, one named contract at a time.