Getting Started with Test-Driven Development - Where Do I Start?

If you have ever built software using a true Test-Driven Development (TDD) approach, do you remember the first problem you had to overcome? Was it perhaps:
Where do I start? What’s the first test?
That’s a very common issue - simply not knowing where to start.

Quite a few years ago, I was coaching at a client in the St. Louis, Missouri area. I attended a meetup of the local XP group and it was a session about exactly this topic. It was being led by Brian Button, and he started by speaking about the blank look that some developers have when faced with figuring out where to start. His exercise was to have us pair up and start building a simple game of Blackjack using only a test-driven approach.

I paired with Brian Nehl, who just happened to work for the Missouri State Gaming Commission. I figured that would give us the upper hand over other pairs. Our platform of choice was C#, although the examples I will show here are in Java.

After a very brief discussion about the rules of Blackjack, we talked a bit about where we wanted to start. Well, we need a Game of some sort, so should we start there? The game will have to be able to compared Hands of cards, so maybe that’s the place to start. But what about players? We’ll need a Dealer and a Player and each will have a Hand.

After perhaps 2–3 minutes, we decided to focus on something more fundamental - the Card. A card would need to have a value, and I believe we even started with the concept of a suit. So our first test was something like:
   @Test
   public void eightOfHeartsIsGreaterThanThreeOfSpades() {
      Card card1 = new Card(8);
      Card card2 = new Card(3);

      assertTrue(card1.getValue() > card2.getValue());
   }
This test forced a few things. First, the compiler griped that there was no such thing as a Card class. So we had to create that:
public class Card {
}
That cleaned up the first errors, but now we were told there wasn’t a getValue method in Card. That was our next step:
   public int getValue() {
      return 0;
   }
The compiler errors were gone and we could run the test. Naturally, the test failed since getValue only returned a zero. That’s great… we now had our first failing test!

I know what you’re thinking… WHOA!! WAIT A MINUTE! You just hard-coded a return value just to please the compiler!

Yes. Yes I did. And that’s OK! TDD is all about expressing the desired behaviour using tests and making the tiniest change possible to allow the tests to pass. In a statically typed language like Java, it’s OK to think of compiler errors as a form of test.

But now we needed to make the test actually pass. So, we changed the code in the Card class to be something like this:
   private int value;

   public Card(value) {
      this.value = value;
   }

   public int getValue() {
      return this.value;
   }
Green bar!! Our test passed!

We added a couple more tests like this, then realized that we hadn’t actually done anything with the concept of a Suit (Hearts, Diamonds, Clubs, Spades). We decided to refactor our tests to pull out any mention of a Suit because we simply didn’t need it at that point in time.
   @Test
   public void eightIsGreaterThanThree() {
      Card card1 = new Card(8);
      Card card2 = new Card(3);

      assertTrue(card1.getValue() > card2.getValue());
   }
We proceeded to write tests that introduced face cards and the Ace. We eventually created the concept of a Hand, and could compare the value of two hands by aggregating he values of the Cards within a Hand.

I believe that was when we had run out of time, as there was only an hour for the coding session. The goal wasn’t to complete the Blackjack game, but rather to get comfortable with starting somewhere.
During the debrief, it was interesting to note that out of 6 pairs, only two started at the same place. Equally interesting was that there was no incorrect place to start!

That was the point of the exercise. If you’re stuck on where to start, just start somewhereanywhere!

A few years later, I attended Agile Games 2011 in Boston. Adam Sroka led a session about using TDD to build a Texas Hold ‘Em game. When we started, I recall several people tried to design the whole “system”, and built a long list of things that had to be done. There was more flailing over where to start.

I sat down with Moss Collum, another developer, and just asked, “Where do you want to start?” He handed me the keyboard and I typed:
   @Test
   public void eightOfHeartsIsGreaterThanThreeOfSpades() {
   }

Conclusion

Since then I’ve used TDD a couple of times for card games. Today I’d probably start with either the Game or the Hand rather than Card. Again, that isn’t because starting with Card was wrong, but I could see getting further in the same amount of time by using a different starting point. Or maybe not - it probably depends on the individual developers.

The main conclusion, though, is that you don’t need to agonize over what the first test should be. You don’t need to agonize over which concept to introduce first. Just start somewhere and adjust from there. The code will show you which way it wants to go.

Comments