3 Aspects of BDD and Agile Requirements
Agile and Behavior-Driven Development (BDD) has become more and more popular recently, so it would be good to discuss more about these topics.
First of all, requirements are not the same as a product specification. A requirement is something which is required by some people. And not just some people, but specific people – the stakeholders.
A stakeholder is someone who has some business in solving some problems — and yes, it could be a user of our software product too. Users are using the software because it helps them to solve some particular problems. It means that they have some business in using it. We could assume that in requirements we mostly want to answer the question: Why the product needs to do some particular things for our stakeholders?
Functional specification is more detailed than requirements. The goal for functional specification is to describe what the product will do to solve particular problems and meet the stakeholder's requirements.
And there is third, the bottom level – technical specification. Here we want to describe how the product will do the functionality described in the Functional Specification section.
You may write the requirements in the user stories format — user stories could help us discover what the requirements are.
And for the functional specification of the product, you may use scenarios, examples, or use cases. There is even a specific pseudo-language designed to do that in a proper way – it is called Gherkin. Thanks to that it is also easy to write automated acceptance tests based on the functional specification. In that case, tests became the specification or specification became tests.
And finally technical specification. Probably the best way to assure that the technical specification is always up to date during the infinite software development process is to use unit tests for that. And probably the best way to write unit tests is use test-driven development.
The Agile Requirements
User stories became more and more popular as a tool to write requirements down.
Standard user story format looks like that:
As a [user role]
I want [some action]
Unfortunately so often user stories looks like that:
As a user
I want to log in into application
So I will be logged in.
It looks awful, and it is ridiculous. If you write users stories like that try to think if you are not wasting time for that. Is there any value in describing requirements in the way like that? Of course, this example is trivial and using user stories for such simple requirements as authentication is a waste of time, but it shows the most common mistake which I have observed in many teams starting their adventure with BDD or Agile Requirements.
The format that I am recommending to my teams is a little bit different. I prefer to write user stories like this:
In order to [business goal]
As a [stakeholder]
I would like to [visible change in software behavior]
First of all, I am starting with a goal because discovering purpose of doing something could eliminate many ridicules requirements. Yes! Eliminating requirements or decreasing amounts of them. It is the best way to keep our products clear and easier to maintain. Not event talking about making the product easier to use.
Secondly, I have changed the regular user perspective to a stakeholder's perspective. That way I am focused on the real value, not just adding some fancy features. Of course, users are often stakeholders too, but there are also other stakeholders for our products like some law regulators, business owners, administrators, back office users etc.
And last but not least, the “visible change in the software behavior” this is what I want. Only visible changes in the functionality could add some value to the product, everything else is just a waste of time.
And there is a reason behind placing “visible changes in the software” at the end of the user story. This order opens the options list, so when I start working on user story by defining a goal and then describing who is the stakeholder for whom this goal is important now I could generate few different options which could cover this requirement. This opened user stories format foster the creativity process.
The Functional Specification
When we already have user story and we chose one (or more) option we could focus on what the product could do to cover this requirement.
This is the moment where we can go into BDD loop. Start with writing some examples. You may use Gherkin – given/when/then convention, where you define context, tested action, and assertions for our use case/example. This way we can create very independent and clear automated acceptance tests.
An example BDD Scenario might look like this:
GIVEN user logged in as admin
WHEN user adds expensive product to the basket
THEN proper discount is added to the total order value
The Technical Specification
After we finally have such functional test written, we could go into Test-Driven Development (TDD) loop and write a code by adding one test after another and refactor everything in each TDD loop. Unit tests written in a Test-Driven Development way will create a nice technical specification for our product. By browsing such tests every developer could answer the question how things work.
That way we could combine requirements, functional specification, and technical specification. Have you notice that there is no additional cost behind this approach? Automated tests and documentation came for free.
When to Use Behavior-Driven Development?
People often claim that they are wasting to much time when using BDD for everything that they are doing, especially for some trivial stuff. BDD is good to be used only when you are dealing with things which are not obvious — especially not obvious for you.
Every time when we have to deal with something which is unknown and we do not have experience in doing such a thing it is a good time to use BDD and user stories.
Every time when we are not sure if we understand the purpose of creating some feature it is a good time to take index cards and write some user stories down.
Another problem which I have noticed is that so often people are writing to many acceptance tests and they are trying to cover every functionality by such a tests. It is very important to limit the amount of the acceptance tests to the absolute minimum. We also want to only have the crucial functionality described in our documentation.
Behavior-Driven Development, Agile Requirements, and Cynefin
Behavior-Driven Development is just one of the tools that professional development team may use if needed. Using Behavior Driven Development for all requirements is usually a waste of time.
I love to explain when to use Behavior Driven Development by explaining Cynefin Framework concept.
You have five areas/categories of problems or requirements for your product: obvious, complicated, complex, chaos, and disorder.
5 Levels of Ignorance
In this article, Liz Keogh described 5 levels of ignorance for software requirements. You can map this levels at the Cynefin Framework:
When I am working with our teams usually we are starting with the requirements classification. We do that to chose the proper method and tools to implement them. The process starts with mapping the backlog at the Cynefin and those 5 levels of ignorance.
3rd Level of Ignorance – a Good Place to Start With BDD
Things that are at 1st and 2nd levels of ignorance usually do not need to be specified and clarified so we do not waste our time to write user stories and scenarios in gherkin for them. Most of the team members know what need to be done at this levels so they should not have any problems with understanding requirements and communication around them. (Beware that obvious is close to chaos and if those type of requirements is not managed at all, it will soon become chaotic and problematic.)
3rd Level of Ignorance – where we have limited access to the domain experts knowledge about how things should work is a perfect place to use Behavior-Driven Development. Here the value is highest and BDD costs (no BDD doesn’t come for free) are justified by the benefits. Behavior-Driven Development as a communication tool works perfectly when we are aiming for fast knowledge sharing and common requirements understanding.
Levels 5th and sometimes 4th – using Behavior-Driven Development here is more like guessing. We do not know how should it work and we do not know if it is even possible to implement particular requirements in a way we describe it in our user stories and scenarios/examples. For this kind of requirements first, we are doing some research and development or reverse engineering work. By creating some prototypes or spikes we are discovering how requirements could be done. What really happens after R&D is that by prototyping and experimenting we gain the knowledge and few experts (former researchers) appears in our organization. So the requirements are moving from 4th and 5th level to the 3rd level where we could successfully re-implement them using Behavior-Driven Development.
Using Behavior-Driven Development at the 5th and 4th level is often confusing. Using it at 1st and 2nd level is a waste of time because it is simply not needed there.