Why TDD Rocks
Yesterday I had (yet another) realization about the power of TDD.
In the latest iteration I’ve been working on adding features onto out new AAA API (see Gil’s recent posts for more info). Feeling in control, I was real confident I was about to finish ahead of time and pick up some tickets from our stretch goal list, when it happened. I added a test that used the API a little differently than what I’ve tested with so far, and quickly realized that this scenario was not properly supported. 5 minutes later I realized it would require a major refactoring to get things ready for a fix to be put into place.
After the initial wave of panic subsided I realized I was in good hands. I had a framework of around 200 passing tests for the feature and the code surrounding it, and now I had a breaking test – an excellent starting point when using TDD.
Now, in the olden days before I started working like this, having to apply a fix that shuffled things around and changed the way interfaces talk to each other was as much fun as pulling teeth with a string and a door – you had to be so careful not to hurt yourself you often preferred not to mess around with it and let the bad tooth stay in there. With TDD it was almost like a game. I quickly (and carefully) went in and changed some things to make the breaking test work. After 2-3 cycles of fixing and re-running the test I was satisfied that this use case was now covered, so I ran the entire test suite again. After the 30 seconds it took the 200+ tests to run, I had 15 failing tests on my hands, but it was pretty easy finding out the commonality between them and quickly fix it. 3-4 cycles later and everything was green – everything that worked before plus the new test. I slapped on another dozen or so tests to make sure I was covering all angles of this usage scenario, and then went in and refactored to make the code read better.
I can just imagine the effort this would take without our test framework to support this task – just applying the initial fix would break 15 usage scenarios which I would have to manually identify, test and debug. Heck, there would be so many unknowns before starting such a task we may have preferred to leave the bad tooth and stick with the pain.
Because we use TDD, it took a couple of hours to fix a serious bug, move a lot of code around (by the way, thank you, Resharper!) and have full confidence that everything works and I didn’t break anything. More importantly my team was able to meet (and even exceed) out iteration goals. For me, this is why TDD rocks.