A Case for Test-Driven Development
If you're on board with unit testing, but not quite sure about test-driven development, I want to share my experience for why I think writing the tests first is the way to go.
You can't write "un-testable" code
It is certainly possible to write code that is difficult or impossible to test. This is especially a problem if you're not thinking about how you're going to test your code as you're writing it.
There are design strategies that you can use to avoid creating un-testable code, but these take experience to know when to apply them correctly.
Writing the tests first forces me to think about how to test my code as I'm writing it. The strategies for making the code testable emerge naturally each time I decide how to write the next test.
It simplifies implementation
Sometimes when I'm faced with implementing a new software module, it can be a bit overwhelming to figure out where to start.
A traditional approach would be to create some sort of design plan upfront and then implement it. However, maintaining the mental model in this approach produces a high cognitive load. It can be hard to keep track of everything in my head.
And... what if something changes as I go along? Maybe I realize that it really shouldn't or can't work that way for some reason? It's more painful to change course.
When I'm test-driving, I let go of that mental model and ask what is the very first, simple thing I need this module to do? It could be as simple as testing some initial value, but it's important and it's a good way to start. Then I write a test that describes the behavior and I implement it.
I just repeat this process over and over, each time asking myself what is the next thing this module needs to do? And, each time I add functionality with a new test I know if I everything I've already done is working because of all of the tests I've created along the way.
I've just taking a large problem and broken it down into a series of simpler, actionable tasks. This is a lot easier for my brain to handle.
You only implement as much as you need
It's easy to want to go off and crank out a lot of code all at once (without tests). But if you do that it might not be clear if all of that functionality is actually needed.
Test-driving forces me to be clear about every piece of functionality that is being implemented.
Each time I write a test I try to only write enough code to pass that test. When I do this, I know that I'm doing exactly the right amount of work to get my software to behave how I need it to.
This gives me confidence that I'm not adding any unnecessary functionality. There's a lot less risk that I'll go and do a whole bunch of extra work. And I'd prefer not doing extra work.
So, I suggest that you try writing the tests first. That is, of course, unless you like writing un-testable code, making things more complicated or doing more work than you have to.
Okay... it's actually a little more work to make the switch to writing the tests first. Once you get the hang of it, though, it'll save you time and effort in the long run.