This article (originally published in Better Software) explores generalization in TDD.
The basic notion is that refactoring sets out to not change the behavior of code for any of its inputs, but TDD sets out to change behavior (in the “code” step). The moves we make in TDD are transformations, but they only preserve behavior for some inputs.
For example, suppose you’re writing code to handle Roman numerals. Perhaps you start from the I = one test but at some point you add support for IV or V: you change the behavior for some strings (IV or V) but not others (I).
Get the article here (PDF).