From 3896a3eccc53e7dbec8b74395fb416a5c55ab1f3 Mon Sep 17 00:00:00 2001 From: wrcapitalcorp Date: Thu, 23 Jul 2026 06:51:56 -0500 Subject: [PATCH] docs(test-driven-development): add guidance for modifying behavior with existing tests The red-green-refactor cycle documents writing new behavior from an empty test file and gives little guidance for changing behavior that is already covered by tests. The only note on that case, "Other tests fail? Fix now," can be read as making a failing test pass without first determining whether the code, rather than the test, is at fault. This adds a "Modifying Existing Behavior" section covering three points: inventory the existing tests before changing code; update the existing test to the new contract first, in the same commit; and, for each additional failing test, decide whether it is a genuine regression (fix the code) or an intended behavior change (update the test). The "Other tests fail?" line under Verify GREEN is updated to state this decision inline and link to the new section. Co-Authored-By: Claude Opus 4.8 --- skills/test-driven-development/SKILL.md | 49 ++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/skills/test-driven-development/SKILL.md b/skills/test-driven-development/SKILL.md index 60d2609ca5..fa33201511 100644 --- a/skills/test-driven-development/SKILL.md +++ b/skills/test-driven-development/SKILL.md @@ -180,7 +180,12 @@ Confirm: **Test fails?** Fix code, not test. -**Other tests fail?** Fix now. +**Other tests fail?** They encode existing behavior your change touched. For each, +answer one question before editing anything: **is the CODE wrong (a regression you +didn't intend) or is this an intended behavior change?** Code wrong → fix the code, +leave the test. Intended change → update the test to the new contract, this same +commit. Never edit a red test green without answering. See [Modifying Existing +Behavior](#modifying-existing-behavior). ### REFACTOR - Clean Up @@ -195,6 +200,48 @@ Keep tests green. Don't add behavior. Next failing test for next feature. +## Modifying Existing Behavior + +The cycle above starts from a blank test file. **Changing** behavior that already +has tests is different: some already-passing tests encode the OLD behavior, and +the failure mode is editing those tests green without asking whether the code is +what's wrong. That turns the regression net into a rubber stamp. + +**1. Inventory the existing tests FIRST.** Before touching code, find every test +that pins the behavior you're about to change. Don't discover them later when CI +goes red — that's how stale tests are born. + +```bash +grep -rn "functionYoureChanging" test/ # by symbol, route, field, or fixture shape +``` + +Can't find a test for behavior you're about to change? Add coverage before changing +it (see "Existing code has no tests" in Common Rationalizations). + +**2. Change the existing test first, in the same commit.** Same red-green, but you +edit the *existing* test, not a new one: update it to the NEW contract, watch it +fail against the current code (proving it pins the behavior), then change the code +to pass. Test and code move in one commit — a contract change whose test lags into +a later commit is exactly how stale tests surface days later. + +**3. When any OTHER test goes red, answer the fork.** For each unexpectedly-red +test, decide before editing: + +> **Is the CODE wrong, or is this an intended behavior change?** + +- **Code wrong (a real regression):** fix the *code*. Leave the test. This is the + test doing its job. +- **Intended change:** update the *test* to the new contract, this same commit. + Legitimate maintenance — *because you consciously decided the change was + intended*, not because green is convenient. + +If you can't say which branch you're on, you don't yet understand your own change. + +**Brittleness smell:** a refactor that changed no observable behavior yet reddened +many tests means those tests were coupled to implementation (exact mock shapes, +call counts), not behavior. Prefer behavior-level assertions so future refactors +don't pay this tax. + ## Good Tests | Quality | Good | Bad |