On BDD: Unit Level Specifications

Earlier I spoke about specifications at the story level, now it’s time to explore them at the unit level. Story level examples explore how the feature in it’s entirety works, demanding code to be produced to make the example work… at the unit level, we apply the same concept, we provide examples that prove the need for code in our class to exist and then write code to make that example work.

Examples, or Exemplars

The basis for this are Exemplars, which we saw earlier in story level specifications, but just to recap they are somewhat equivalent to scenarios consisting of the structure

Given (Some Context/Precondition)
When (Event Happens)
Then (Outcome)

You might recognize this structure from an existing TDD practice of “Arrange, Act, Assert.” Hypothetically I like to think of this as the same format and we should aim to keep each three phases of the exemplar as small as possible. In JUnit I might write an exemplar somewhat like this (using an example from the BDD wikipedia page):

	@Test
	public void shouldNotBeEmptyWhenListHasMoreThanOneItem(){
		List<String> list = new ArrayList<String>();

		list.add("foo");

		assertFalse(list.isEmpty());
	}

In the above example, the given/when/then would be

Given a new list
When an item is added
Then the list should not be empty

From there I’ll create more examples of how the API should work, refining and adding examples in an attempt to “break the model”, that is attempt to define examples that break my assumptions on how the API should work and even provides better insight on what roles/collaborations my object might have. Now this doesn’t mean wasting time by passing null to every method call or writing fifty exhaustive examples with every possible input known to man, but rather finding examples that could prove that my domain logic is incorrect… by doing so, I’m able to reflect on my current API design and refine my model.

The main process at work here that ties this together is something I first saw at a Real Options based presention (as well as in the comic I mentioned in my earlier post): David Kolb’s learning styles model which I think accurately reflects the development cycle that one often uses when applying BDD style practices. To break the process down into Kolb’s Cycle:

  1. Concrete Experience: seek challenge and immediate experience - I like to think of this as coming up with the first example and writing code to make that example work
  2. Reviewing the Experience: ‘stand back’, gather data, ponder and analyse – We wrote an example with passing code, what have we learned from this experience? I also like to think this is the point where we might refactor, not only to clean code up, but to refactor toward deeper insight.
  3. Concluding from the Experience: think things through in logical steps, assimilate disparate facts into coherent theories - we’ve analyzed the example and solution, refactored towards deeper insight, now we have several ideas of where to go next
  4. Planning the next steps: seek and try out new ideas - this connects us back to step one, we try out successive examples and new examples we’ve come up with, and we’re not shy to try an example out and discard it if it’s incorrect

I know that sounds like quite a bit of work, but I often find that this process occurs naturally and can be pretty rapid, building each example off of the previous examples, seeing patterns and refactoring, and even eliminating bogus examples. Especially if you’re pair programming it helps if you are doing “ping pong” style pair programming: writing the first example, your peer writes just enough code to make the example work, then uses his concrete experience to write the next example for you to write code to work.

So What’s the Real Point?

I think the biggest point to convey here is what the difference is between conventional “unit testing” and a BDD mindset… in the earlier, you might be concerned with testing your code but what you should do is be focusing on providing examples of how your code works and using those examples to prove the need for your code. That mindset coupled with writing examples in the Given/When/Then format keeping them simple and to the point helps you drive the design of your API and even provide some developer readable documentation on how the API works.

Next?

Again, I’m only barely scratching the surface… there’s a lot more to talk about, and a lot more to delve into in how best practices in TDD are present in BDD. I haven’t even covered any BDD specific spec frameworks, opting to provide examples only in JUnit! There’s also more to discuss on Contexts, Test Doubles, etc. Stay tuned!

You can leave a response, or trackback from your own site.

Facebook comments:

Leave a Reply

Subscribe to RSS Feed Follow me on Twitter!