tags:

views:

39

answers:

2

The first part of the TDD cycle is selecting a test to fail. I'd like to start a community wiki about this selection process.

Sometimes selecting the test to start with is obvious, start with the low hanging fruit. For example when writing a parser, an easy test to start with is the one that handles no input:

def testEmptyInput():
  result = parser.parse("")
  assertNullResult(result)

Some tests are easy to pass requiring little implementation code, as in the above example.

Other tests require complex slabs of implementation code to pass, and I'm left with the feeling I haven't done the the "easiest thing possible to get the test to pass". It's at this point I stop trying to pass this test, and select a new test to try to pass, in the hope that it will reveal an easier implementation for the problematic implementation.

I'd like to explore some of the characteristic of these easy and challenging tests, how they impact testcase selection and ordering.

How does test selection relate to topdown and bottom up strategies? Can anyone recommend writings that addresses these strategies in relation to TDD?

+2  A: 

I start by anchoring the most valuable behaviour of the code.

For instance, if it's a validator, I'll start by making sure it says that valid objects are valuable. Now we can showcase the code, train users not to do stupid things, etc. - even if the validator never gets implemented any further. After that, I start adding the edge cases, with the most dangerous validation mistakes first.

If I start with a parser, rather than start with an empty string, I might start with something typical but simple that I want to parse and something I'd like to get out of that. For me unit tests are more like examples of how I'm going to want to use the code.

I also follow BDD's practice of naming the tests should - so for your example I'd have shouldReturnNullIfTheInputIsEmpty(). This helps me identify the next most important thing the code should do.

This is also related to BDD's "outside-in". Here are a couple of blog posts I wrote which might help: Pixie Driven Development and Bug Driven Development. Bug Driven Development helps me to work out what the next bit of system-level functionality I need should be, which then helps me find the next unit test.

Hope this gives you a slightly different perspective, anyway - good luck!

Lunivore
+1  A: 

To begin with, I'll pick a simple typical case and write a test for it.

While I'm writing the implementation I'll pay attention to corner cases that my code handles incorrectly. Then I'll write tests for those cases.

Otherwise I'll look for things that the function in question should do, but doesn't.

Marius Gedminas