Test Driven Development: What, Why, and How?
If you’re in the business of writing code (or leading teams that do so), Test Driven Development has likely come up at some point. Maybe it’s even been pitched as a possible development cycle in your team or organization.
And most likely, this push has been met with resistance. While any change will meet some reluctance, the resistance to TDD likely stems from a few unfortunate misconceptions that keep teams from realizing the benefits of this development process.
What is Test Driven Development?
There are many articles (and always Wikipedia) to give you background on this, so I’ll keep it brief. TDD is a development cycle that puts the writing of unit tests at the “beginning” of the cycle. There are three laws of TDD, but these two principles are the easiest to digest:
- Write only enough of a unit test to fail (red phase)
- Write only enough production code to make the failing unit test pass (green phase)
The key philosophy to keep in mind is minimalism. Hence the not-so-subtle bold and italic above. We’ll come back to this.
The production code that tries to get the test to pass is not going to be elegant. Indeed, it does not need to be. It just needs to be enough to work. Why is this acceptable? Because the process has a third step saved just for refactoring.
The best way I’ve heard it described is that the red light phase is all about showing off skills to users, while the refactoring phase is all about showing off skills to other developers. In other words, being able to write simple tests challenges you to really understand what the code needs to achieve for the user, while refactoring is about achieving code quality.
Why Adopt TDD?
There are a few common misconceptions which are ironically the key reasons more people don’t adopt TDD. The biggest? “It takes more time.”
While it always takes some time to adjust to change, once the adjustment period ends (and if TDD has been appropriately trained and followed), it takes no more time than you are spending today. On the contrary, depending on your current practices and codebase this process could save immense amounts of time in the following ways:
- More extensive test coverage means fewer bugs and faster debugging
- Initial focus on test drives engineer to really understand what users need meaning higher chances of your production code having impactful results
- Minimalist approach reduces chances of over-engineering where it’s not necessary
- Built-in refactor step ensures consistent awareness of code quality, which keeps the code base legible and easy for your compadres (and in turn, you) to develop new features
- The test coverage, with the necessary listing of all valid and invalid inputs, creates an easily understood (and necessarily up-to-date) documentation package for API work
Beyond these more pragmatic reasons, there’s a psychological benefit as well. As an engineer, you’ve likely experienced a moment in time when you’ve got all your code working, and you are rightfully excited, but then your soul drops in despair as you have to go and write all the necessary tests.
By always writing a test first, you set yourself a goal such that, once you hit it, you can feel good that your job is really “done.” I say “done” because it’s a cycle; of course you have to keep working, but at least you can enjoy that little dopamine release that will keep you driving forward.
How Do I Implement TDD?
This is an organizational question. First and foremost you need support, and support begins with a sell. You must first understand the what and why of TDD. For a more technical version of the “what,” check out this example walkthrough. As for the why… you just read it!
Then you must sell the idea to whoever will listen. If you’re an engineer, start with your direct manager. If you’re the CTO, talk with your managers. If you’re a manager, you get the job of selling everyone below you and above you (you can always tell them to read this article!).
The only way to really realize the value of TDD is to take a leap of faith and see the results, both pragmatic and psychological. This doesn’t need to be your whole company at once. If there’s an especially adventurous independent team, have them try it out and report back as ambassadors of the change.
Test Driven Development isn’t for everyone. Maybe your test coverage is thorough, your code is high quality, bugs are a rare and simple nuisance, and users are consistently grateful of every line of code you write.
If this doesn’t sound like you, consider trying TDD. While it may feel backward or wasteful, reframing your development in this way can be a huge time saver and the results can be great in terms of time saved, headaches avoided and general happiness achieved while you plug away at your terminal.