ad-hockery: /ad·hok'@r·ee/, n.
Gratuitous assumptions... which lead to the appearance of semi-intelligent behavior but are in fact entirely arbitrary. Jargon File

How can test it if I don't know what I'm building yet?

One objection to the practice of TDD I’ve heard from several different people is along the lines of “I don’t know exactly what I’m building at the outset, the code is experimental, so how can I write tests for it?”

Frequently it is the case that you have an idea but don’t know the mechanics of how you’re going to implement it. I find this particularly when I’m writing code that extends a third-party library. You don’t know exactly where the API hooks you’ll need to use are, your understanding of the API is fuzzy and you expect to learn it as you go. So how do you test-drive in that situation?

XP has a recommendation here: write a spike then throw the code away once you have enough understanding of the technical solution to approach the problem in a more rigorous manner. In my experience that practice, while valid, doesn’t sell TDD to a doubter.

What I think really causes the original objection is that the person in question is thinking at the wrong level. They’re mentally diving straight in to code, to the solution, to the elegant and shining temple of technical brilliance they’re about to erect. They’re thinking about how not what.

Step back. Sure, you don’t know what your code is going to look like or how it’s going to interface with anything. If you try to start with low-level unit tests now you will spend a lot of time re-writing tests for fine-grained interactions when you need to take a different approach.

Two things you do know are what is going in to this thing you’re going to build and what you want to come out of the other side.[1] So test that. Test that at a high level.

Writing a static asset pipeline that concatenates and minifies JavaScript and CSS files? Write a test that uses example files and makes assertions about what the result should look like. Writing an authentication system for a web-app? Write some browser-based tests that register accounts, log in, log out and verify authentication state via the user interface that doesn’t exist yet. If you’re using Cucumber you don’t need to implement all the detail of the steps yet. If you’re using Spock or JUnit (or RSpec, Scalaz, Jasmine or whatever) then compose an abstraction for the tests and leave out undefined details you don’t know. Use sensible assumptions you can easily change (we’re probably going to ask for a username and password), no-op helper methods (we don’t know exactly how we’ll verify the user is logged in just yet so we’ll write a helper isLoggedInAs(username)), elide over the irrelevant detail (we might require some other information when a user registers but we can add that later).

None of those things require you to know how the code you’re going to write is going to work. They require you to think about and formally specify what you expect in the way of input and output. It forces you to define the coarse-grained behavior of the software you’re designing – what you want it to do. The how now has a framework for success into which it can grow.

In Growing Object-Oriented Software Guided By Tests Steve Freeman and Nat Pryce describe this style of testing as outside-in. You start with high level tests using a “walking skeleton” and progressively work inward adding more detail and drilling down to low-level unit tests and the accompanying fine-grained behavior. The walking skeleton is fleshed out as you go and by the end of the process has evolved into a passing end-to-end acceptance test suite.

1 If you don’t know that I’m pretty sure you need to figure it out before you start writing any code.
Web Statistics