I feel like, lately, a lot of my blog posts start the same way: I explain that I didn’t particularly like something in the past, then follow that up with how my perception changed. This time its different: I love TDD with my whole being, and did so from the very start.
There were, however, times when Test Driven Development and I didn’t stand on the best of terms. And, being fair with this wonderful software development process: I was wrong in all of them.
TDD wasn’t any less amazing when I didn’t like it. I just didn’t have enough experience to use it to its full potential. And this lack of vision kept me from reaping the full benefits of the approach; which in turn caused me frustration.
But as time went by, and I kept using the approach over and over again, I slowly began to see the light. And once I began to really understand it, TDD showed me a new world I didn’t even know existed, one of certainty and easy refactors.
And I’m here to share that world with you today, if you wish to join me.
What is TDD?
Test Driven Development (TDD) is a programming approach in which a developer:
- Writes a unit test (yes, just one.)
- Runs it, and see’s that it fails.
- Writes enough code to make it pass (and not one character more.)
- Runs the test again, see’s that it succeeds.
- Repeats until all features are done building.
And just so we don’t leave any stone unturned: A Unit Test is a type of test that gets applied to a single area or function (referred to as a unit) of our code.
These tests are usually derived from the Acceptance Criteria, meaning that they tend to resemble the needs of the business. Which, in turn, means they’ll influence your final product to be a lot closer to what the business actually wanted.
Simple enough, right? We’re developing units of code by testing them first, writing enough code to make the tests pass, and then repeating the process until we’re done coding.
And now that we understand the concepts, let’s get to what this approach actually does for you and your team.
The pros and cons of TDD.
I first came across TDD when I started to focus more on Front End Development. It all happened when our head of QA came to my team looking for input on a presentation.
I really wanted to make a good impression on everybody so, naturally, I offered to help. The topic of that presentation was Test Driven Development for the Front End, and I quickly became its main supporter.
This doesn’t mean I quickly understood everything about the topic, but I knew enough to sell the idea. And that meant having a grasp of what the pros and cons of TDD actually were.
Adopting a new programming philosophy is bound to come with its own set of tradeoffs, and Test Driven Development is no different.
Let’s start off with the pros:
- Simpler, easier to re-use code (since it has to be easy to test.)
- Code that more closely resembles the needs of the business.
- Less refactoring.
- Easier integration.
- Resulting tests can serve as secondary documentation for the code base.
- Less bugs.
And continue with, to my knowledge, the main con:
- A very steep learning curve.
And by learning curve I don’t mean that TDD is difficult to understand. In fact, we just saw that TDD is an intentionally simple concept to get a hold of. But that doesn’t mean that it is a simple concept to apply.
While the benefits vastly outweigh the negatives, there’s one thing that needs to be mentioned: The TDD learning curve WILL make you painfully slow at first.
And while the curve can last from 2 to 4 months in some teams, for me it was… A bit more complicated, to say the least.
Writing meaningful tests.
While my coworkers began to slowly accept TDD into their lives, I was feeling like a kid with a new toy. So I did what anybody would do when they’re overly excited with something new: I started applying it to everything.
This being Test Driven Development we’re talking about here, that meant I was writing test cases (also known as specs) for pretty much every possible scenario.
This is not how you do test driven development. At all. And it took me a long time to figure it out.
I wasn’t the only one having these problems, however. Once pretty much everybody had adopted TDD, you could basically encounter two kinds of testing suits (groups of tests):
- The ones without enough test cases.
- The ones that tested pretty much every possible case in existence, and then some.
Author’s Note: You can actually check how much of your code you’re actually testing by using Code Coverage Tools. Warning: High test coverage does not equal High quality of tests.
Both of these symptoms were caused by the same concept: We knew how to test (perfectly well, may I add), but we didn’t yet understand what to test and why.
I believe the answer to both of those questions depends on the tools you’re using and the project you’re working on. There is, however, one key question that I believe should be asked before writing any single piece of code (tests included):
Is my code adding value to the final product?
Asking this question before writing a unit test will help you understand that:
- Not all test cases add value to the final product.
- Not all specs are created equal (they don’t all add the same amount of value.)
And it’ll help you reach the point where you know what tests to write and why. Getting to this level of understanding, to me, marks the end of your TDD learning curve.
TDD: A story of ups, downs, and ups again.
After spending a while in the dark, contemplating whether or not TDD was even worth it, I finally came across my answer when I started doing my own projects (as part of learning new technologies.)
I forced myself to use TDD in everything I wrote, regardless of what design pattern I was using, which eventually got me to see things I couldn’t see before.
What I found there was certainty and ease of refactoring: Regardless of what I changed, I could be sure that, if my tests passed, everything was alright.
One. Hundred. Percent. Sure.
That is an amazing feeling to have, and I’m not trading it any time soon.
Author’s Note: If you’re interested in some extra credits reading, you really can’t do much better than Test Driven Development: By Example by Kent Beck.