A few weeks ago I attended an informative in-house TTD (Test Driven Design/Development) educational session run by Tom Quinn – colleague and Principle Development Consultant at iMeta. This session was run as a hands-on coding-dojo style format. For me, it was a great ‘goof-and-learn’ lunch hour experience where a group of us made headway developing the ‘Rock, Paper, Scissors’ game, TDD style.
As with many other developers, my coding style prior to bumping into TDD was the ‘Test After’ approach. In the ‘Test After’ approach, you write unit tests against code you have just completed. The focus is about Unit Tests. With TDD, the focus is Design. While the concept of TDD is simple, making the head-shift and mastering the art, takes time.
Anyone practicing TDD will know that at the forefront of the approach is the ‘Red, Green, Refactor’ mantra. For readers who are not familiar with this:
- Red: Write a test that fails
- Green: Make a change to the code to allow the test to pass (no matter how ugly the code)
- Refactor: Clean up ugly code and remove duplication of the code written to get the test to pass
During the dojo session, Tom recommended Kent Beck’s book Test-Driven Development By Example. So I grabbed a copy and have just completed reading it. I want to highlight one important point I noted in the book that I feel has the potential to get lost along the way when following TDD principles (because the RGR mantra is so loud and strong). With the mantra banging away in the head, a developer might be tempted to:- grab a user story from a task list; think of a scenario that applies to that user story; and get to work. However, there is one important thing you should do before you let that pounding of the mantra start. Take a step back and Write a list of all the tests you know you will have to write in order complete the scenario. We might all do something a little like this. However, following this to the degree recommended by Kent appears to be a discipline worthwhile adhering to.
In order to be in a position to write down a list of tests, you are forced to evaluate the user story to a depth you might otherwise not have. This helps tease out, not only headline tests, but also additional relevant tests. This process might also help one eliminate tests initially thought to be relevant. Obviously, the act of physically writing down tests you identify will allow you to better select - and then mentally focus on - the most appropriate test when you get down to do the work. As with the creation of any list, you are freed of the need to maintain the list in your head. As TDD has a lot to do with stress and fear reduction, freeing the mind of anything that adds unnecessary clutter to the mind – such as trying to remember lists - is part of TDD.
Kent recommends that the list should be comprised of:
- Tests of operations you know you want to implement
- Null versions of operations that do not already exist
- All refactoring you think you will need to do to end up with clean code
He also recommends refining the list into “Now” (this coding session) and “Later” (subsequent coding session). During a coding session, work from the “Now” list of tests. Pick off one test at a time, and keep the list dynamic. To this dynamic list add new points discovered; and strike out those points completed.
As an example, if we are writing a test to verify the calculation of the maximum value a facility might grant to an applicant for a mortgage, our dynamic now list could end up something along the lines of:
Term - Principal Only
Rounding ? Payment Option (Principal only / Interest and Principal) - Type (Fixed / Floating)
Applicant Current Age
Maintaining such a running list which is frequently amended in sync with the rapid RGR cycles of TDD, helps keep the focus on the what needs to be accomplished and guards against items dropping off the list. Something likely to occur if one attempts to hold this information in your head.