I have been doing test driven development on a standard 3-tier web application for around 2 years now. Initially I felt that doing bottom up development was the best thing to do. It was easy for me to think of small domain objects on the service side that seemed to have small pieces of the entire story. Unit test these small pieces, check them in and you feel good. The next step was to integrate these pieces by driving it through an integration test, and you have the service side done. No problems until now. The next step is to integrate the UI layer by calling the service and using it’s output. Everything looks fine until you look at the fine print in the acceptance criteria which you in your excitement to write unit tests had failed to consider on the service side. Sometimes the service contract that you thought was perfect starts looking flawed because of some weird acceptance criterion. Now starts the layer volleyball, you start plugging the holes between the UI and the service side. If the criteria force you to change the service contract, you will start adding fields like flags to the contract just to sign the damn story off.
This is a very good example of what I call waterfall thinking. Just think about it, you start coding one layer, finish it and then move on to the next. If you discover a new requirement or understand the requirement better as you move your way through the story, then your service layer is sort of ‘frozen’ for change. It is the same problem that the waterfall model faces in ‘classical software engineering’. Late changes become expensive. Most developers who come from a waterfall shop to an agile one (including me) show these symptoms. We are also successful convincing the Business analysts to split stories in to services and UI ones. The quality analysts are then forced to test essentially what are the same acceptance criteria in two different ways (one on the service side and the other on the UI). It is an even bigger nightmare to showcase the service stories to the customer because their outputs are so ‘texty’ and unintuitive. The customer is never interested in whether you wrote a service with an awesome contract, he/she just needs to the see the end output on the website. Period.
Stories need to be based on smallish features that they deliver, which are a subset of a bigger feature scheduled for a release/iteration. Some people call it vertical slicing where you have a piece of each layer in a story as opposed to horizontal slicing where each layer is a story. For developers it is very difficult to understand all the changes in the services layer upfront during iteration planning. It is more important to understand how the feature on the UI works more than the implementation details. When you start development if you start driving your services code from the UI, you might find more scenarios that you might have skipped during iteration planning. Your service contract starts to evolve more gracefully, as opposed to mutation in the waterfall approach. You initially stub the services layer to fake the expected output from your services. This makes sure that you have all your bases covered before you hit the services layer. You can drive it using functional tests if possible, so that you are driving it from a test using the ”red-green’ philosophy. Personally I think that the functional tests should be written by the quality analysts, since the developers may not write tests for all scenarios. Again this approach is debatable. You can drive in whichever way you are comfortable with, but the bottom line is that top down makes you understand the fine print early, which leads to better code from the start and less refactoring later.