To TDD or Not to TDD?
If you’re new to programming, you may not be familiar with the term TDD, or Test-Driven Development. This is an agile practice that emphasizes writing automated tests before writing the production code. It is a great, profound philosophy that results in source code that is thoroughly unit-testable.
Despite all the great benefits TDD offers, it comes with a cost. If applied inappropriately, it can dramatically delay the production of software. In my experience, TDD is a productivity killer when you’re working on a new concept with limited time and budget. You may have to try various ideas and see what works. The requirements and user experience may change rapidly in every iteration. In situations like this, if you adopt TDD, you’ll end up fixing a lot of broken tests or throwing out lots of production code or tests, because the concept keeps changing.
Also, personally I think TDD works best when you pair with another programmer to help you stay focused. As you switch between writing tests and production code, you may easily get distracted from the original task and get lost in details. So having another programmer at your side who has the roadmap helps you stay on track and be productive.
Real World Example
In one of my recent projects, my colleague and I worked on a completely new concept. I was the developer and he was the user or client. Neither of us were sure where to start and how the ultimate experience should eventually look. So I started by showing him various mock-ups of the initial concept. In every iteration I added lots of new stuff while removing or changing the existing capabilities. I couldn’t afford to write tests for everything because the concept itself was changing so quickly. Four months passed and we got to the stage where we both thought, “That’s the way to go.” At that point, we had a roughly stable concept and I started writing automated tests.
If I had written lots of automated tests and applied TDD religiously in the beginning, I would never have been able to come up with this concept in four months. Instead of focusing on innovation and developing a product, I would have wasted a lot of time fixing lots and lots of broken tests for production code that would eventually be thrown away! The project owner had a limited budget and if the project had taken too long, he would have run out of funds and we would never have been able to finish the project.
Sometimes manual testing can be much faster than writing automated tests. I remember one of the mistakes I made on another project was spending almost two days writing some unit tests for one of my pages with a lot of Javascript. It would take me only a couple of clicks to test those features. Later on, the concept changed a lot and the page that I wrote automated tests for was removed! None of those automated tests were applicable any more. So those two days of writing unit tests and mocking dependencies were wasted. Imagine if I had spent two weeks rather than two days on this!
That said, in the same project, there was a case where TDD significantly helped me. I needed to implement a few business rules in my domain model classes. I thought it would take me far longer to manually test each of these rules. I would have to run the application, do a few clicks and enter some data to test each variation of the rule. Instead, I approached that problem using TDD and it worked perfectly.
So, To TDD or not to TDD?
So, as you see, I’m neither promoting nor dismissing TDD. It requires making decisions on a case-by-case basis. If you want to be a productive programmer, or a ninja coder, you need to stop being dogmatic about practices like automated testing or TDD. Applying any practice religiously just because you love it or a book told you about it is a recipe for failure. For every project, you should think about trade-offs. Take into account the client you’re dealing with, costs, deadlines, complexity and other factors.
Decide whether manual or automated testing will take you to the destination faster. Your goal should be to deliver an appropriate and efficient solution to a problem within a reasonable timeframe at a reasonable cost. There is lots of competition out there, and you should always think ahead of others and launch your software product as soon as possible while maintaining its quality.