Test Driven Development helps me creating better software. TDD is not only about testing. It's more about designing and managing scope. I'll try to show what I mean by using a simple example based on tabbedimages application.
Tabbedimages is a simple image viewer. We are going to add drag and drop feature to it.
I start with a requirement, which I analyze and spike for a working solution. Based on the analysis I create a user story and an automated acceptance test. The acceptance test "drives" me when I'll add unit tests and the production code.
- tabbedimages is a simple image viewer.
- We want to add a new feature to tabbedimages.
- 'Drag&drop support'.
- TIP: It's good to have a short title for a user story.
- Analysis: let's list things to worry about:
- Single image files
- Multiple image files
- Non-image files
- Already open image.
- TIP: This part should give us better understanding of the problem
- If we're sure how to implement the new feature we can skip this step.
- tabbedimages is implemented using IronPython and Windows Forms.
- The code is availalable here.
- Google for 'drag and drop windowsforms' and see some code examples.
- Check out the fresh version of tabbedimages.
- Try to add the required feature to our code base (without tests).
- Discover that Windows Forms has support for DragDropEffect.
- Which displays a 'plus' sign if the thing that we're trying to drag is acceptable.
- Add the DragDropEffect to the list of things to worry about.
- User story:
- Marten wants to drag and drop his images from his desktop to tabbedimages.
- He starts tabbedimages.
- He then drags the 'Faye001.jpg' file over the application.
- The plus sign appears.
- He drops it.
- A new tab is created with a label saying 'Faye001.jpg'
- 'She's cute' he thinks
- Marten realizes that there are more Faye's pictures.
- He drags 'Faye001.jpg' (again) and 'Faye002.jpg'.
- He drops them.
- Two new tabs are created.
- He drags and drops readme.txt file.
- The message box appears saying 'readme.txt doesn't appear to be a valid image file'
- He quits tabbedimages.
- Functional test:
- Write the ideal code (DSL-like) that follows the user story steps:
fayes_pictures = ['Faye001.jpg', 'Faye002.jpg']
he.asserts_tab_labels(['Faye001.jpg', Faye001.jpg', Faye002.jpg'])
he.sees_message_box("readme.txt doesn't appear to be a valid image file")
- Run the Functional Test (FT).
- Whenever FT fails or you can think of any edge cases not covered by FT:
- Write appropriate Unit Test that reflects the problem.
- Add the implementation to fix the problem.