The Problem with Specifications
The traditional way of building software is to write down everything that the customer wants in a document called a specification or requirements document.
It doesn't work very well.
Here's something I wrote way back in 2005-06 :
In technical software projects, clients are generally unfamiliar with not only the concepts and terminology but also with the functionality that is being described to them.
Typically, the experts go through a lengthy and detailed design process and deliver a custom built solution, tailor-made to fit the client’s requirements.
At this point the client looks at it and says: “That’s not what I want!”
And the developer/BA/designer blurts out: “But that’s what you asked for!”
There has been a fundamental breakdown in communications and on one knows why.
The problem stems from the fact that the project team are experienced software practitioners and the client is not. They are used to interpreting specifications and the client is not. When a developer sees “a multi-function hierarchical picklist” in a spec they understand what it means.The client sees convincing techno-babble delivered by a competent technical expert and (at first) nods vigorously.
In recent years, the rise of Agile has spurred an interest in what might be called 'lightweight' forms of requirements documentation. This is because there has been a recognition that pursuing ever more elaborate forms of documentation does not solve the requirements gap I illustrate above.
What is needed is more elaborate forms of communication and discussion.
User Stories & Acceptance Criteria
A user story or feature describes functionality that delivers value to a user or a customer. It tells a story about how someone uses the product and what they will achieve with it.
It is not meant to encapsulate the whole requirement – it is meant to be an easily understandable placeholder for the conversation that takes place about the requirement.
Acceptance criteria or scenarios are rules which confirm the completeness and correctness of a user story. How will we know when a user story is complete in the system? It is done, when the system complies with the acceptance criteria.
As a story is discussed, the acceptance criteria develop and confirm the exact behaviour of the system under certain conditions. Acceptance criteria start out simple and develop into more formal and structured statements as the requirement is better understood.
The easiest way to learn to write user stories and acceptance criteria is by using “patterns”. By using these patterns repeatedly you form a common language within your team that you use to describe your requirements; which reduces ambiguity.
Users stories or Features
As a [type of user]
I want [a feature]
So that [I get a benefit]
Acceptance Criteria or Scenarios
Given [a known state]
When [I perform an action]
Then [something happens]
Rules of Thumb
- Each user story should have about 3-5 acceptance criteria
- Each story should be independent and stateless – it should not rely on another story. If it does, you should consider splitting the story into sub-stories.
- Avoid implementation details and focus on outcomes – don’t say how a thing is to be done, but what the outcome should be.
- If you can’t write any acceptance criteria for your story then it’s likely that it can’t be implemented!
Standardising Your Language
In order to make the best use of user stories and acceptance criteria you need to standardise your language. If you refer to a “user” in one acceptance criteria and an “end-user” in another then it won’t be clear whether you are referring to the same thing.
To this end, you should create a dictionary to be use with your acceptance criteria that specifies what each keyword means. Each keyword should have only a single meaning and the same keyword should always be used for the same artefact (user, field, screen etc).
- And – you can extend each simple clause of an acceptance criteria by using “and” to specify another clause. For example when I fill the kettle with water AND plug it into the electricity AND turn it on
- Background – if you have a number of acceptance criteria which have common clauses you can use a “background” statement to make them easier to read. Typically the background statement contains the common “given” and “when” statements for all clauses, but the “then” (outcomes) will be unique.
The pattern for criteria is from a language called “Gherkin”.
Gherkin works with an interpreter called Cucumber and a range of other tools to provide an automated testing stack for software. By interpreting the acceptance criteria through Cucumber and then using another layer to bolt it onto your specific system you can automatically test all of your requirements.
This is known as having executable specifications.
You can choose to execute each test manually or automatically but by doing them automatically you can quickly home in on what has changed and what might be broken and use the manual effort to diagnose the problem.
From “The Cucumber Book” :
The idea of automated acceptance tests originates in eXtreme Programming (XP), specifically in the practice of Test-Driven Development (TDD).
Instead of a business stakeholder passing requirements to the development team without much opportunity for feedback, the developer and stakeholder collaborate to write automated tests that express the outcome that the stakeholder wants.
We call them acceptance tests because they express what the software needs to do in order for the stakeholder to find it acceptable. The test fails at the time of writing, because no code has been written yet, but it captures what the stakeholder cares about and gives everyone a clear signal as to what it will take to be done.
These tests are different from unit tests, which are aimed at developers and help them to drive out and check their software designs. It’s sometimes said that unit tests ensure you build the thing right, while acceptance tests ensure you build the right thing.
The concept of executable specifications can be extended to Behaviour Driven Development (BDD).
BDD couples together Test Driven Development and it's unit tests with the business scenario testing of BDD to produce an end-to-end lifecycle for a requirement and it's implementation in code.
At it's ultimate extreme, BDD allows you to write self-documenting, self-testing code.