Since there are a few debates going on (again!) about whether BDD is just TDD done well, I thought it might be interesting to showcase some examples where BDD language made a difference to people’s understanding.
Original Poster wrote:
In TDD development, the first thing you typically do is to create your interface and then begin writing your unit tests against that interface. As you progress through the TDD process you would end-up creating a class that implements the interface and then at some point your unit test would pass.
I wrote: Please let me rephrase this in BDD language:
When describing why a class is valuable and how it behaves, the first thing you typically do is to create an example of how to use the class, often via its interface*. As you add desired behavior you end up creating a class which provides that value, and then at some point your example works.
*May be an actual Interface or simply the accessible API of the class, eg: Ruby doesn’t have interfaces.
This is why you don’t test private methods – because a test is an example of how to use the class, and you can’t actually use them.
Response: Brilliant post. Clarifies a lot.
Instead of writing a test, you’re going to write an example of how you can use your class (and you can’t use it except through public methods). You’re going to show why your class is valuable to other classes. You’re defining the scope of your class’s responsibilities, while showing (through mocks) what responsibilities are delegated elsewhere.
At the same time, you can question whether the responsibilities are appropriate, and tune the methods on your class to be as intuitively usable as possible. You’re looking for code which is easy to understand and use, rather than code which is easy to write.
If you can think in terms of examples and providing value through behaviour, you’ll create code that’s easy to use, with examples and descriptions that other people can follow. You’ll make your code safe and easy to change. If you think about testing, you’ll pin it down so that nobody can break it. You’ll make it hard to change.
Response: good answer! very concise!
From comments on my blog post, “Translating TDD to BDD”:
Ben asked: Given this terminology, can you reword these sentences to eliminate the TDD terminology, but in such a way that someone who doesn’t know what BDD is can understand it?
Writing the tests first ensures that the code we write to make them pass is actually testable. Otherwise, we may wind up with classes and methods that, although fairly well designed, are not easily tested
Writing examples of how to use the code, before we write the code that makes those examples work, ensures that the code we write is easy to use and understand. Otherwise, we may wind up with code that, although adhering to SOLID principles, has been written to be easy to write rather than easy to use or maintain.
(Of course, if you’re doing true outside-in then you already have one example of how to use a piece of code, from its consuming class. I reworded this from ‘well-designed’ to ‘adhering to SOLID principles’, since they’re necessary for good design but IMHO not sufficient.)
Ben responded: Liz, that’s beautiful. I especially like how you phrased your points about use and maintenance. Takes the focus off “testing” and puts it on something that’s more directly tied to value.
Taking it up a level, again from StackOverflow, Are BDD tests acceptance tests?
BDD “tests” exist at multiple different levels of granularity, all the way up to the initial project vision. Most people know about the scenarios. A few people remember that BDD started off with the word “should” as a replacement for JUnit’s “test” – as a replacement for TDD. The reason I put “tests” in quotes is because BDD isn’t really about testing; it’s focused on finding the places where there’s a lack or mismatch of understanding.
Because of that focus, the conversations are much more important than the BDD tools.
Acceptance testing doesn’t actually mandate the conversations, and usually works from the assumption that the tests you’re writing are the right tests. In BDD we assume that we don’t know what we’re doing (and probably don’t know that we don’t know). This is why we use things like “Given, When, Then” – so that we can have conversations around the scenarios and / or unit-level examples.
We don’t call them “acceptance tests” because you can’t ask a business person “Please help me with my acceptance test”. Try “I’d like to talk to you about the scenario where…” instead. Or, “Can you give me an example?” Either of these are good. Calling them “Acceptance tests” starts making people think that you’re actually doing testing, which would imply that you know what you’re doing and just want to make sure you’ve done it. At that point, conversations tend to focus on how quickly you can get the wrong thing out, instead of about the fact you’re getting out the wrong thing.
Response: 20 upvotes and a “nice answer” badge!
These are just a few instances of using BDD’s language instead of TDD’s. I’ve found it even more powerful in spoken language, and more powerful still when talking to business-focused stakeholders about examples of how we might use a system to deliver the value they want. I taught BDD to my dad once, showing him how to write examples in Java in order to ensure that his code would be usable and maintainable. After we’d written a couple of classes, I said, “Of course, this also gives you a nice set of regression tests.”
“Oh, yes!” he said, “So it does. I hadn’t thought of that.”