Sunday, July 24, 2011

Test-Driven Development Is Not Slower

Hello, my name is Matt Honeycutt, and I am addicted to Test Driven Development.  I’ve been “using” for about 5 years now.  It started out with a little innocent unit testing and Test Later Development, but I quickly found that the increased productivity caused by TDD to be too alluring, and I succumbed.  Now I’m using all the time.  I use at work.  I use at home.  I just can’t stop.  People don’t really understand the risks.  There’s this myth that TDD is slower, that it makes you less productive, but that’s so not true.  Read on, and I’ll help you understand why.
NOTE: This post is an extended version of a comment I left in reply to an anonymous commenter on Mike Hadlow’s “I Don’t Have Time For Unit Tests” post.  I encourage you to go read his post, because Mike has some good insights that I won’t repeat here.

If there’s one myth about Test Driven Development that annoys me, it’s that TDD is somehow “slower.”  Slower than what, I ask?  Slower than just cranking out code without testing it?  Slower than fixing a bug without first reproducing and understanding it?  Slower than making changes and hoping, nay, praying, that you are wise enough to not make a mistake?  TDD is slower than what, exactly? 
Here’s the comment that has me all riled up:
Instead of writing tests I just don't write any code without knowing thoroughly how it will affect functionality around and system as a whole. And since my code is dead obvious - that costs nothing.

There are some other problems with this like high "bus factor" (what if I'm being hit by bus - who would replace me?) but for development speed - closely followed TDD would slow me down for 100%.
There are a lot of false assumptions in this reasoning.  First, except for trivially small applications that you never have to maintain, you can never be sure you know "thoroughly how it will affect functionality around and system as a whole." That's one of the reasons automated regression tests, like those produced as a by-product of TDD, are so valuable: we suck at accounting for how our changes may affect other code or how they'll impact existing requirements.  That line of code you’re about to delete because you don’t see why it’s necessary?  It turns out that was added to work around some particular edge case that occurs during leap years.  Removing that line of code will reintroduce a bug that was costing your company (potentially) thousands of dollars.  If the code base you were working on was built using TDD, you’d know that, because you’d get a failing test when you removed that line. 
Second, I would assume you are indeed testing your code somehow as you create it (if not, please stop writing code now). You may be doing that by running the app and exercising the affected functionality integration-style, but you're still testing it. All TDD does is move that testing effort to the front, put your tests closer to the code you are changing, improve your design, and provide you with faster feedback.  I would bet that I can also run my automated unit (or integration) test much faster than you can launch your app and test your change manually.
As a nice by product of TDD, you also gain automated regression tests, documentation, etc.  Think of how much time those things are going to save you over the life of your application.  remember, maintenance is the most expensive part of software development.  So no, I don't buy at all that doing TDD slows you down unless you aren't testing the code you write in the first place, and if you aren’t testing somehow, you aren’t a developer, and you shouldn’t be producing code in the first place. 
That said, there is indeed a learning curve to TDD.  It’s called a practice for a reason: you will get better at it only by using it.  At first, the thought process of “red, green, refactor” will most likely feel unnatural.  It may feel uncomfortable.  Stick with it though, push through that pain (and invest in good tools, such as a test runner that integrates into your IDE, a mocking framework, and my personal favorite, SpecsFor), and I promise that you will be more productive in the end.

1 comment:

H said...

TDD is helpful when we write large software.

When some code changed, TDD let us know where does it affect