Getting Started with Getting Started: Yet Another TDD Post
Sit back for a second and think: what’s the scariest moment when starting a new project? For me, it’s sitting in front of an empty code file. I mean, I have the latest versions of Visual Studio and Windows on my machine (2012 and 8, respectively, at the time of writing), everything is humming along nicely, all this power at my fingertips – and nothing to apply it to. I’m staring at an abyss. It’s absolutely terrifying.
I had always thought that it’s just me and my personal biases, but recently I had the chance to witness this same phenomenon in others as well. Some background: part of my job at Sela is teaching basic software development skills to students. Among these skills we also teach them C#. So we would go over some feature of the language, I would give them a coding assignment and let them have a go at it. And several times I saw two of my brightest students stare at the screens in front of them with a look of absolute horror on their faces. So I walk over and ask them what’s wrong. The answer": “I don’t know where to begin”. They understood the assignment and had a rough idea of how they would approach it in terms of class and method design. But actually writing the first lines of code required some kind of leap that was paralyzing them. I guided them through the first class and method declarations and it was smooth sailing from there on.
And this got me thinking – how do I handle these situations? What is it that allows me to overcome this dread of empty projects? In my case, I apply Test-Driven Development. You’ve probably heard of TDD – if not, look it up and you’ll find lots of material on the Net (try here for a concise introduction). The key for me is the first principle – writing a failing unit test before writing production code. If it’s the first test in the project (or, for that matter in a completely new part of the application), I write what I call a warm-up test. It’s a test whose only purpose in life is to get me from nothing (an empty project) to something. Enhancing or fixing existing code is nowhere near as frightening as starting something new.
The contents of a warm-up test are almost trivial. It’s a class declaration, maybe a method or property call, and an assertion that ensures the most basic conditions on a new instance of the actual production class (also known as System-Under-Test or SUT). That is, it answers the question – what can I say about a brand-new, just-out-of-the-factory instance? By answering the question I get a test. Test code is code – in fact, it’s code that obviously can’t run since the SUT does not exist yet. But hey, my project is not empty anymore!
If we look closely, we can also see that what we just did is more than just write a bit of trivial code. We also did some design on the way. Granted, not a lot of design – but enough to get us started and pointing in the right direction. Adding any additional code that has applicative value is now easier, since we have an existing object and well-defined behavior for a new instance.
Let’s look at a simple example: the venerable BankAccount class. A warm-up test checks this new instance and ensures that its balance is exactly 0 – no debt and no credit. So my first lines of code would be:
public class BankAccountTests
public void ctor_HasZeroBalance()
var account = new BankAccount();
The end result – my project is not empty and there is a list of tasks that await me: I have a class to declare, a property to add along with a simple implementation that I’m comfortable with. Plenty of work. Phew, that was scary there for a while!