BDD was the subject matter being discussed at May's London Altnet beers. After the talk I was discussing with some people about their approach to doing BDD. What was being presented was the idea that BDD specs are useful only at the outer layers of the application and once you get more low level, you should revert to normal style TDD tests.
I don't agree. I have been writing BDD specs for every single class I write, and have recently upgraded our build system (rock on TeamCity) to make the spec reports. Saying BDD is just for the outer layers is ignoring the fact that the users of application know a lot more about their business than you do.
I'll give an example. We are building a system for the traders to view their trades - in what is known in the financial world as a "blotter". Being a WPF application, we build the ViewModels first and then build some sort of data access component. So the requirement is that all the trades made today should be displayed on the blotter when the user refreshes it. Here is a set of specs which say that
when the user refreshes the blotter and no trades have been made today
- should display a message saying there are no trades
- refresh button should be enabled
when the user refreshes the blotter and two trades have been made today
- should be two trades displayed in the blotter
- should display the earlier trade on the first row
- should display the later trade on the second row
So now we write some tests for that, and flesh out our implementation. During this time we create an interface ITradeProvider with a method GetTradesForToday(), and use a mocking framework to stub out the calls to that method using our favourite mocking framework.
Our user/customer/business analyst would definitely find those specs useful, and may even give some feedback or changes, which is great. But what about the TradeProvider implementation? Is that worth doing it for? Some would say no, but I would say. We could start off with something like this:
when loading todays trades
- should load todays trades
- should not load trades from a previous date
That's not really saying anything useful is it. Or is it? Imagine you show this to your users and/or business analysts. They're gonna ask:
"What on earth does that mean? When loading today's trades, should load today's trades? It doesn't make sense! We're a bank, we have loads of trade systems, which one are you getting the trades from?"
"Oh right, well I was going to get them from the MYZ team's Oracle database which we got the trades from on the last project I worked on"
"Ok, that's fine, but that's only going to work for trades outside of Asia. For the trades on the Asian stockmarkets, we're going to have to get the data from the AYN team located in Singapore. They have a web interface for looking at the trades and I think they provide some sort of service for you to retrieve it from"
"Oh OK, thanks! I'll update the specs and get back to you to review them again!"
You may think this is a fairly contrived example, but it's the sort of thing you will come up with time and time again. As developers, we move from project to project all the time, and we often make assumptions based on previous projects. Users, on the other hand, are getting you to build a system to provide value to their business. They are likely to know it a lot better than you! Business Analysts especially have a very detailed knowledge of all the internal systems and what their responsibilities are (though they may not have the kind of deep technical knowledge you have of communications protocols, etc).
So think twice about abandoning BDD for the lower layers of the system. Write the specs, share them, invite everyone you possibly can to review them. The earlier problems are found in a system, the cheaper they are to fix. That's been proven through countless studies.