Boston used to have a software craftsmanship meetup. One month, on the train going home, a few of us discussed "how to describe TDD". Someone had a teaching gig coming up. That night, I attempted to distill the views expressed by this couple of experienced TDD folks. Here it is, FWIW.
# What is TDD?
TDD is JIT-development, built on tests.
It's not developing things before you need them. That's too easy to get wrong. It's not built on reviews and approvals. They're too slow and fragile.
## TDD's JIT development with tests is:
1. Live in the present.
Focus effort on what is clearly useful progress now, not speculation.
Don't do planning or development before you need to. Because later, you will better know what is actually needed, if anything. Be restrained but thoughtful in judging how much of what, needs to be done now.
Don't put off integration. Until then, usefulness and spec are only speculative.
2. JIT-spec
Capture each behavior you care about as a test.
Keep them simple, small, and clear. A new spec is a failing test. A passing test means "done with that -- next!".
Don't stuff your mouth. Don't do lumps. Keep it bite-sized.
Don't spec it until you need it, even if you (speculate) you know where you are going later.
Don't worry about the spec having to change later. They usually do. If the speced behavior is clearly useful now to make progress, that's good enough. If it's something you don't really care about long-term, you can remove it later.
3. JIT-implementation
Keep implementation minimal.
Don't create speculative code. Do reactive implementation and refactoring. If you "might need it later", write it later, when you have clearer need and spec, and more tests available.
## About tests.
Programs have a few behaviors you care about, and many more that are implementation details. Test the behaviors you care about.
Tests redistribute development flexibility and speed.
* Behaviors pinned down by tests, are harder to change. Because you have to update the tests too. They're transparent but rigid, and change is slower.
* All other behaviors, become much easier to change. Because everything you care about is tested, implementation changes can be done energetically, without careful cautiousness and fear of accidental hidden breakage. They're opaque but flexible, and change is faster.
Distribute your transparency and flexibility wisely.
Some topics I'm notably unclear on include test refactoring and management.
* when does one delete tests?
* how are lines of development pivoted?
* how are different classes of tests handled? (eg: external spec commitment; less critical spec I still care about; sentinel spec, which I don't mind changing, but I don't want it to happen accidentally/silently; spec that's transient development scaffolding, and should be removed later; and so on)
Opportunities include:
* broader coverage of the strategy, test, and implementation layer activities
* description of how test suites and implementations change longer-term
* specific discussion of cross-cutting issues like risk mitigation
* tighter characterization of core (eg, all tests and code are a burden, and start with a high time discount, so create and retain only those which are clearly and currently useful)