← ClaudeAtlas

legacy-code-testinglisted

Adds tests to legacy code that has none, safely: characterization tests that pin current behavior (including bugs) before any refactoring, seam identification for breaking untestable dependencies, and a risk-ranked coverage strategy. Use for untested or inherited codebases. Triggers on: "add tests to legacy code", "this code has no tests", "characterization tests", "make this testable", "safe to refactor?", "pin down current behavior", "test this old module before we change it".
timwukp/agent-skills-best-practice · ★ 3 · Testing & QA · score 79
Install: claude install-skill timwukp/agent-skills-best-practice
# Legacy Code Testing Untested code you must change is a trap: you can't refactor safely without tests, and you can't test cleanly without refactoring. The way out is characterization testing — pin down what the code *currently does* (not what it should do), then refactor under that safety net. The golden rule: **before refactoring, tests assert current behavior — even buggy behavior.** A characterization test that "fails" because the code has a bug is wrong; the test must pass against today's code. Log suspected bugs separately for the team to triage. ## Process 1. **Scope and rank.** Identify what actually needs a safety net: code you're about to change, plus its blast radius (callers and shared state). Rank by `change-likelihood × consequence-of-breaking`. Do not attempt whole-codebase coverage — legacy coverage is bought module by module, just-in-time. 2. **Find the seams.** For each target, identify where behavior can be observed and where dependencies can be substituted without editing the logic under test (see Seams table). If there is no seam, apply the *minimal* enabling refactor (extract method, parameterize constructor, wrap static call) — mechanical, behavior-preserving, small enough to eyeball. 3. **Write characterization tests.** - Start with the happy path for the most common input; then boundaries (empty, null, max, malformed); then the weird branches the code visibly handles. - When you don't know the expected output, **run the code and capture it**