diff --git a/lazy-tdd/SKILL.md b/lazy-tdd/SKILL.md new file mode 100644 index 0000000..7db4f04 --- /dev/null +++ b/lazy-tdd/SKILL.md @@ -0,0 +1,50 @@ +--- +name: lazy-tdd +description: Lazy TDD / test-driven debugging — use when a bug, goof, regression, or "that didn't work" is discovered in code you wrote; when fixing a failing behavior; when refactoring; or when deciding whether new code needs tests. Code that works the first time may ship untested; a discovered goof means you owe a test that reproduces it before (or with) the fix. +--- + +# Lazy TDD + +From Dan Connolly's +[2006 resolution: no more undocumented, untested code](https://www.madmode.com/2006/advogato_entry0044.html) +(MadMode, Mar 2006): + +> It's best to write the tests first … For personal projects, I'm not +> disciplined enough to write the tests first every time; if the code I +> write works the first time, I sometimes let myself get away with it. +> But I'm doing pretty well about doing test-driven debugging, at least. +> I write tests for any code that doesn't work the first time. And I +> write tests when I refactor and change things. The confidence to make +> changes that comes from having tests in place is very freeing. + +## the deal + +1. **Got it right the first time? No test owed.** Writing tests first is + still best, but it's not required here. Don't pad a change with tests + nobody asked for. +2. **Goof discovered? You owe a test.** Any bug in code you wrote — found + by you, the operator, CI, a reviewer, or a runtime failure — earns a + regression test. No fix ships without it. +3. **Refactoring or changing behavior? Write tests** covering what you're + about to touch, so the change is made with confidence. + +## paying the debt (test-driven debugging) + +1. Write a test that reproduces the goof, in the project's existing test + framework and style, next to related tests. +2. Run it; **watch it fail** for the reason you expect. A test that + passes before the fix proves nothing about the fix. +3. Fix the code. +4. Run it; watch it pass. Run the neighboring suite too. +5. Commit the test with the fix (same commit, or test first). + +Name the test for the behavior, not the bug ticket: "rejects negative +amounts", not "fix for goof #3". + +## when a test is genuinely impractical + +If the goof can't reasonably be captured in an automated test (e.g. it +lives in config, a one-off script, or untestable I/O with no seam), say +so explicitly, explain why, and suggest the seam that would make it +testable (see [ocap-discipline](../ocap-discipline/SKILL.md) for +injecting I/O). Don't silently skip the debt.