If a class is well-designed, it will be easy to unit test. Good
design speeds up unit testing, and TDD reveals bad design. In
this way, TDD speeds up unit testing.
For a very simple example, consider a controller class that takes a
domain object and saves it to the database using a data access
class. When test-driving this code, it will be impossible to
create a unit test for this if it is poorly designed. Consider
this poor design: the SaveXX() method instantiates the data
access class and passes the domain object to it for saving. With
TDD it would be impossible to write a unit test for that because you
can’t fake the data access class, and you must test the controller
class apart from the dependency on the data access layer.
Because of the major roadblock in designing a test for code designed
poorly, it forces the developer to come up with a better design.
This better design will be a cinch to unit test because it will be
loosely coupled. Loose coupling is essential for unit testing.
To write a test for this controller class, I’ll have to define an
interface for this portion of the data access layer. I’ll inject
this interface into the constructor of the controller class and call it
in my SaveXX() method. With this design pending, I can fake the
interface in my test and assert that it was called with the correct
object. This will be my test. Next, I’ll write the code
that makes the test pass.
Poorly designed code is hard to test, and thinking about testability
will force a more thoughtful design. I would even go as far to
say that at the class level, a testable class is a well-designed class.