This article was excerpted from "Specification by Example using Gherkin" by Kamil Nicieja. Read the article to get a 39% discount code for the book, issued exclusively for DZone’s readers.
Humanizing technology is the greatest challenge of software engineering. The tech industry must show great empathy for the problems of other people. We’re making tools for everyone out there. It’s an important responsibility.
In the messy world of organizational politics, broken workflows, human errors and biases, technology experts must figure out how to collaborate successfully if they don’t want to fail in their mission.
To do so, they need specifications.
What’s a Specification?
Imagine that you and your team have been brought in to work on a new version of a management system for a local public transport company. What would be your course of action right after you get on board?
Maybe you’ll write the requirements down in a functional requirements document. You also may, for example, encapsulate requirements within user stories or use cases. Either way, functional requirements documents, user stories, and use cases are all examples of specifications or specifying methods.
Traditionally, specifications have had a bad reputation in the software development community. The reason is half psychological, half practical.
Psychologically, specifications offer a promise of cooking recipes. They invite a "just follow the steps and everything will be all right" mindset. The promise is as reassuring as it is deceiving. In practice, creating a complete specification is extremely difficult, if not impossible.
Meet Specification By Example and Gherkin
Out of the many tools and methodologies introduced by the community to reshape traditional specification methods, I find two of them particularly interesting. They’re called Specification by Example and Gherkin.
Specification by Example, a methodology that sprang from the agile acceptance testing’s tree, is a collaborative approach to defining software requirements based on illustrating executable specifications with concrete examples. It aims to reduce the level of abstraction as early in the process as possible to get everyone on the same page and reduce future rework.
Gherkin, a business-readable domain specific language, provides a framework for business analysis and acceptance testing. Gherkin will help us understand the requirements from the perspective of our customers. By forcing ourselves to think about what a user’s workflow will look like, Gherkin will facilitate creating precise acceptance criteria.
Below is an example of a specification written in Gherkin.
Listing 1 Example
Feature: Setting starting points and destinations Scenario: Starting point should be set to current location Given a commuter that enabled location tracking When the commuter wants to plan a journey Then the starting point should be set to current location Scenario: Commuters should be able to choose bus stops and locations Given a bus stop at Edison Street And a Edison Business Center building at Main Street When the commuter chooses a destination Then the commuter should be able to choose Edison Street But the commuter should be also able to choose Edison Business Center
Having conversations that identify business needs
The main premise of Specification by Example and Gherkin is that frequent conversations between domain experts and the delivery team lay a foundation for the entire development process.
Figure 1 Having conversations should provide delivery teams with all the answers necessary for understanding a project’s goals, who customers are and what solution they need
A conversation is when:
the public transport company’s management wants to build new modules into their timetables system and you discuss their business needs together
an angry customer explains Edison Business Center shouldn’t be interpreted as Edison Street by your mobile app because they’re not the same thing
two engineers discuss whether the system should treat a bus route as a collection of 2D points on a map or a straight line between the start point and the destination point
a commuter files a bug report about the bus scheduling functionality
you read customer feedback on social media and discover what new functionalities they want
Illustrating requirements with examples
Specification by Example and Gherkin require delivery teams to support their conversations with practical examples. Illustrating requirements with examples helps reduce their level of abstraction and helps them devise clearer acceptance criteria.
Humans love stories illustrated with examples. Clear storytelling invites good examples, because examples help us build better mental models of the new concepts we encounter. They’re anchors. Links. Cognitive shortcuts. Most importantly, they reduce the likelihood of misunderstanding the purpose of a story.
Requirements illustrated with good examples should inherit all these benefits. They should be simpler to digest and easier to keep in your head. Let’s take a look at a conversation without any concrete examples and a conversation full of examples to see if that’s true.
Here’s the first conversation.
"OK, so how should the application work?"
"I suppose that when commuters download our mobile app, they should be able to provide a starting point and a destination point, and see a timetable with all the bus lines and departure times they might find helpful in getting to the destination. It’s very simple, really."
"Seems that way."
Such a conversation raises more questions than it answers. What are the starting points and destination points? Are they streets? Bus stops? Buildings and other places? And what exactly may a commuter "find helpful in getting to the destination?" There’s no way we can know for sure.
What would happen, though, if we asked for concrete examples during the discussion?
"OK, so how should the application work?"
"Let’s not jump to conclusions. Imagine for a moment that you’re in the city, say, on a business trip. How and when do you get here?"
"Well, I guess you might arrive a day earlier to be sure nothing goes wrong."
"So we’re going to need a functionality to filter the timetables by date."
"Yes, we are. But let’s consider what happens if the commuter is a bit more happy-go-lucky and arrives in the city an hour before the meeting. You don’t have enough time to check where you are. Or maybe you don’t know the exact street you must arrive to."
"Wow, we might need to implement a GPS geolocation functionality so we can help the users know their current location."
"Yeah, and there should be some option for searching for locations such as parks, buildings or restaurants instead of just bus stops' names."
"Seems that way."
Conversations with examples look similar to short stories about a system’s behaviors. Good stories are vivid and build a platform for fertile discussion between the people who read them. Bad stories confuse readers and leave people clueless.
The same is true for good and bad specifications.
Long-term Benefits of Automating Conversations
After they collect the examples, Specification by Example’s practitioners create specifications out of conversations they have written down.
Figure 2 Automation turns conversations into executable test cases that, if validated frequently, become long-term system documentation.
They then automate the conversations and examples with software tests, and validate the implemented system frequently with these tests to make sure the specification stays up to date.
Automating Tests Based On Examples
Automating ties conversations and examples with system behaviors they describe, which lets you get a binary response about every conversation you captured. A conversation either passes your test, and the behavior was implemented correctly, or it fails, and the system is incomplete or broken.
Figure 3 Specification by Example’s practices fill conversations with meaningful examples that help the delivery team understand requirements they’re working with. Good examples also make tests better and more business-driven. Specification by Example’s tests cover real-world use cases which were provided by business stakeholders and customers. These tests verify whether the delivery team implemented requirements in a way that brings the most business value.
If an example passes the test, you know that the acceptance criteria illustrated by the example are still relevant. If the example fails the test, you get a notification that the changed codebase doesn’t satisfy the acceptance criteria anymore—and that the examples should change to reflect that.
Why is that? Imagine, for example, that our public transport company introduced a new kind of express bus. These vehicles skip most of the bus stops on their way in order to get to the destination point faster. Your team now needs to add express buses to the mobile app. It’s a simple change in terms of code. Somebody must add a new attribute to the database that determines whether a bus line is an express line or a regular one. Easy peasy. You make the change quickly, and then have a lunch break.
That’s when all hell breaks loose. (Almost.)
We forgot that the timetables module isn’t the only one affected. The mobile app you develop also features a live map that shows how the buses closest to you move around. A commuter can check which buses are which in the legend on the map. The legend is generated automatically, but adding the new type of express buses broke the programing logic behind it. As a result, the legend disappeared. For a few days before you took notice, commuters not only weren’t able to distinguish express buses from regular buses—they weren’t able to find any buses on the map.
If you had any documentation in place, the change made it inaccurate and outdated. Nobody updated the document, because you all wanted to just have lunch. That’s what usually happens: People forget; production hot fixes creep in; the Four Horsemen of the Apocalypse drop by. And when the dust settles, our carefully prepared documentation doesn’t reflect the current state of the system anymore. In this case, it doesn’t tell the reader that there are two types of buses and it doesn’t explain what the difference is between one and another. Step by step, with every hotfix and every negligent change, such documentation becomes irrelevant.
None of these problems would arise if your conversations and examples were automated. When conversations are run as tests, we can regularly track which ones behave correctly and which ones don’t. If you test frequently and your specification is exhaustive, you’ll get instant feedback after you make any change to the codebase.
You can validate during the development process or before a release—what matters is that you must do it often. The more often you test, the sooner you can spot possible errors.
Since Specification by Example and Gherkin see development as a process of constant discovery through reducing uncertainty about requirements, the model of the system is, by definition, not fully defined from the beginning—it’s only defined well enough. It evolves continuously based on the feedback from your stakeholders, and new examples and domain concepts enter the specification as new elements are added to the code.
When tests keep specifications in check, they let specifications with examples evolve into a documentation system.
As much as we would want it to be otherwise, only working production code holds the truth about the system. Most specification becomes outdated before the project is delivered. Since every product is a machine made out of thousands of moving parts, it’s a curse of all software projects.
Outdated documentation may seem like a reliable source of knowledge about the system, but it only misleads its readers. But an automated, frequently tested specification—as well as the examples included inside—is resistant to such problems.
The direct connection between scenarios and code often reduces the damage by cultivating a system of living documentation. Living documentation is documentation that evolves alongside the system it documents.
Thanks to frequent validation, you know that your tests, examples, and conversations are up to date, and when you trust your tests, you can use them as documentation for the entire system. You can track every test back to its origin—the conversation you had with your stakeholders about the requirement. When in doubt, you or anyone else on your team can always check the captured conversation. Validating frequently guarantees the documentation must change every time the product changes.
Capturing Conversations as Executable Specifications
OK, so automating conversations has a lot of benefits… but how exactly are they automated? Should programmers store conversations as comments in their testing code? That would be ridiculous—but they have to be written somewhere, don’t they? A free-flowing conversation is, by definition, an unreliable medium that only stimulates short-term memory.
Figure 4 Capturing conversations aims to preserve verbal product design chats as lightweight, long-term, formalized stories that, in the long run, could be used to put system documentation together.
Gherkin is the tool for capturing conversations about the requirements in a formalized way, clarified by extracting essential information and removing noise. Gherkin facilitates knowledge sharing between all stakeholders, regardless of their technical skill. It does so by conveying tests and system behaviors within a ready-for-automation template expressed in plain English that uses the ubiquitous language of a product.
Gherkin focuses on capturing conversations as scenarios. Scenarios extract essential information and remove noise by extracting concrete actions from conversations.
You can find an example of a scenario below. Remember the conversation we had about how the mobile app for journey planning should work like?
"Let’s imagine that I’m in the city on the business trip. When do I get here?"
"Well, if you’re a bit happy-go-lucky and arrive to the city an hour before the meeting, you don’t have enough time to check where you are."
"Wow, we might need to implement a GPS geolocation functionality, so we could help the users know their current location."
Here’s the same conversation expressed as a scenario written in Gherkin.
Listing 2 Example
Given a commuter that enabled mobile location tracking When the commuter wants to plan a journey Then the starting point should be set to current location
Scenarios look similar to user stories and use cases. That’s because both user stories and Gherkin scenarios are tools for capturing business needs and requirements. User stories capture requirements to allow project management, estimating and conversations. Scenarios do the same in terms of exploring requirements. Each scenario is a short story about the acceptance criterion it was based on. If the system fulfills the criteria, the system’s behaving as it was designed.
Just as having conversations improves a delivery team’s short-term understanding, capturing conversations ensures they don’t let their knowledge slip through their fingers in the future. Scenarios achieve that, while reminding us that you don’t need a hundred-page-long functional requirements documents to capture what’s valuable. You don’t even have to write all the scenarios up-front. You can capture a few scenarios at a time as you discuss every new requirement. A few months in, you’ll have a huge library of relevant scenarios. You just need to be consistent.
Every scenario should:
Define context (the givens)
Describe an event that occurs within the system (the whens)
Ensure that expected outcomes take place (the thens)
The sequence is called the Given-When-Then template.
The contents you put in the template should use a non-technical language that heavily relies on real-world business concepts. Notice how the example mentioned "commuters," "journeys," and "the starting point"—concepts borrowed from the business vocabulary of our public transport company—but didn’t say anything about low-level development procedures or the application’s user interface. Scenarios captured using the Given-When-Then template should stay at a business-readable, code-free level at all times, improving the domain model and building its ubiquitous language.
TIP: If you see anything about a database connection in a scenario, somebody did it wrong.
If they’re automated and can be run as automated tests, scenarios can be called executable specifications. Gherkin’s syntax captures scenarios in a form that easily translates to executable specifications. The syntax serves as a link between speech, text, and automated code. It lets you progress naturally from one to another.
Every executable specification usually contains many scenarios and every scenario needs multiple examples. In its rough form, an example is like a quick note or a doodle. It makes sense when you look at it a day after you made it, but try examining it six months later… not so meaningful anymore, right?
Figure 5 Every acceptance criterion generates new examples; every example generates new scenarios. Teams should refine their specifications to merge similar examples, reject the ones that introduce noise, and choose the most meaningful or descriptive ones.
That’s why successful teams don’t use raw examples; they refine them. They extract the essence from the key examples and turn it into clear and unambiguous, perfectly understandable specification documents.
Making Software That Matters
When software engineers and designers don’t put enough thought into their specifications, the cost is measured in weeks of work and hundreds of thousands of dollars wasted.
The benefits of Specification by Example and Gherkin go far beyond just reducing rework. You’ll get better insight into your business domain and reduce friction caused by inevitable translation costs that come up when a business requirement becomes working software. People made these tools and processes because they wanted to guarantee the software they help to make will make sense to its customers. They wanted to make software that matters. Software that helps the entire world, and that both you and I would benefit from.
Welcome to Specification by Example and Gherkin.
To learn more about Specification by Example and Gherkin see "Specification by Example using Gherkin" at Manning Publications and save 39% with discount code nicieja2dz