Behavior-driven development (BDD) explained by example

Kong To
10 min readOct 31, 2019

--

Fundamentals of BDD with three steps : discovery, formulate, automation.

With this article, we will walk through the behavior-driven development methodology.

BDD & 3 amigos

Let’s jump straight in with an example of a behavioral test for a cash machine.

A Scenario Example

The first thing to notice is that the scenario is written in plain English.

The second thing to notice is the scenario has three parts:

  • Given : it’s the arrangement of context state — the starting state
  • When : it’s the event, a trigger or when a user does something
  • Then : it’s the outcome with the expected results

Once scenarios are ready, the development team can begin their work. Each scenario become a test with glue code. The glue code is the test implementation written in a certain programming language.

The, if we run them — and in the absence of any production code — they would fail. As more and more production code is written, tests will begin to turn from red to green. When they are all green, the job is done. That is the way of test-first approach like Test-Driven Development (TDD).

Unit Test vs Behavior Test?

Behavioral tests can be written for a system at any time: before, during or after development.

It can be very difficult to write unit tests for an existing system, because it is structuring, or it requires the existing code to be very modular. Unit tests are written against small block of code.

On the other hand, writing behavioral tests for an existing system does not hit any special difficulty. Because it shall consider the system under test as a black-box. What matter is the the behavior, and not how it is structured within it.

Why BDD ?

If we look at the Given-When-Then format with the example above, we do see a plain English nature of the scenario with a context, an event and the outcomes. That format is the what the business people can focus on, what matters to the customer. And it describes the behaviors of the system under test. The case where these scenarios are written first is name Behavior-Driven Development. That is the test-first approach, and that is what BDD aims for, and it is more important than the automated tests afterward.

What matter is the shared understanding. By collaborating, we can get a better understanding without barrier and have a common language.

Collaboration

BDD is an approach to establish collaboration between the product owner, testers and developers and why not stakeholders. It’s a way to get to find and drive the value in the product we are trying to deliver, rather than having a siloed approach — the traditional way of developing software.

Common Language

The last piece is the common language. When people are collaborating together, discussion about what matters, and the value of product, they need to use the same language to ensure they understand each other. The common language is about having the same vocabulary, business oriented.

Automated Tests

When we think about BDD, we think about automated testing, or acceptance automated testing. We can come up with Cucumber, JBehave or some other frameworks. However, doing only acceptance automated testing does not mean BDD. The same idea goes for the case where behavioral tests are written during or after development. They aren’t be considered as BDD. That is just testing, as we have known for decades. There are aspects of BDD that incorporates automated acceptance testing, but BDD is not just about that. There are two parts that are missing: the collaboration and the common language.

The Approach

The BDD approach is based on three major steps : discover, formulate and automate. The first on is quite important as it will drive all the work that follow.

Discover

During that first step, we may go through a tres amigos workshop to reach a common understanding at multiple levels and so we can surface uncertainty to deliver software that matters. The stakeholder and product owner are not just telling about something to be done. They are talking about the business needs. So instead of giving directives on what to do, they start a collaborating phase and discuss about what they need, with developers and testers. What is important here is all about starting a discussion between the stakeholder/production owner and developers and testers to bring up the value that the business wants, by asking questions and providing examples that translate business needs.

Formulate

During the discussion, we would use a common language, and start using a vocabulary that everyone agree on. Once everything is clear, we can write down everything, using the agreed vocabulary, then we will have a resulting dictionary which we can refer to during the entire software life cycle. And we would formulate the shared understanding into scenarios, using Gherkin format (Given, When, Then).

Automation

At last, we will use the scenarios as input to automate tests. In this article we will see an example with Cucumber implementation to automate scenarios.

Tres Amigos

During the discussion, we would put 3 parties in the same meeting room (or virtual meeting room). The tres amigos concept relies on three perspectives - or roles: Business, Development, Testing.

  • Business

The business perspective could be represented by a Stakeholder, Product Owner or a Business Analyst or both. They are to raise to the surface problems we are trying to solve.

  • Development

The development perspective could be represented by developers, a technical Leader or Architects. They will help to build a solution to solve that problem.

  • Testing

Testers, QA engineers, or sometimes developers will brings in their expertises in testing the product to make sure the quality is met. This workshop would bring to them another angle to tackle functional testing. And they would prevent from things that could possibly happen in an unhappy path?

Example Mapping

The Example Mapping is BDD technic, and is inherited from the tres amigos concept. People holding different perspectives should collaborate to discuss all the details, to define what to do and agree on how to do it correctly. The end result of such a collaboration results in a clearer description of the work leading to a shared understanding for the team.

A product owner chooses a story and writes the business rules. For each rule, he identifies the data to be used and the expected results. Data should cover all business cases, and the way to achieve that is using examples. From these examples, we can write down scenarios (given, when, then), in an order. They are then used for tests automation in that same order. If there is anything that is not clear enough, regarding the rules or the data, the three parties would ask questions and get answers to make sure they get out of the workshop with concrete and usable scenarios for User Stories. Those scenarios are in fact the acceptance criteria for the user story.

Best Practices — Writing scenarios BRIEFE-ly

From the examples out of the example mapping workshop, we would likely write down many scenarios. Depending on the complexity of the feature or user story, we may end up with several scenarios. However, there are some best practices when it comes to formulate them. The BRIEFE principle may be of help.

  • Business vocabulary : use the agreed vocabulary among the tres amigos. That means anyone can understand. Avoid using terms that others can’t understand.
  • Real data — concrete : use real data when explaining something, they serve as examples to represent the idea we want to tell.
  • Intention : A sample must have only reason to exist. Name it with intention.
  • Essential : A sample must help to understand the behavior described in the scenario. If it does not, it’s useless.
  • Focus : There is only one interaction within a scenario.
  • Empathy : Samples describe what the user is trying to do, rather than what he does. This helps to understand and maintain. Describe the behavior rather than prescribing actions. This aims to build empathy for a better user experience.

Benefits

Perhaps the greatest strength of behavioral tests is that they describe, in a very direct way, what the user can expect from the system, with a focus on how the system under test behave. Behaviors are derived from a “contract” that the system is supposed to exhibit. If all the behavioral tests pass then the contract has been upheld. If any of the tests fail, the contract will be broken.

There is another benefit here that may not be immediately obvious. As a developer, we have a tendency to write too much code or code that does too much or code that includes some degree of supposed “future proofing.” BDD is helping to keep focus on getting the behavior test to pass. Nothing less — and nothing more.

So we have these things as a bonus by the way :

  • Having automated tests (unit and functional)
  • Having a living documentation
  • Favoring design driven and test driven development
  • Good functional and code coverage

Drawbacks

If all of this sounds too good to be true, it comes with some drawbacks:

  • Behavior tests tend to be a bit slower to run than unit tests
  • When they fail, they only indicate that something went wrong, but may give little or no indication of the root cause

DONT’s

  • One thing to avoid, because it is usually misunderstood, is to limiting three amigo discussions to only three people. The three perspectives are about roles, not about people. If there are other stakeholders who are relevant to a particular increment of work, include them in the discussion.
  • Also avoid expanding the three amigos discussions to the whole team, thus too many people. The intent of this practice is to include each necessary perspective with as small a group as possible. The smaller it is, the more efficient it is.

Automation with an example

Adding up the automation step, where we drive the development of each work item by using the scenarios written in acceptance criteria, we are optimizing our work on delivering focused and expected values.

Let’s go through the automation with Cucumber and Spring.

Step 1: Bootstrap a spring application with cucumber

You may refer to this repository bootstrap-spring-cucumber-java to bootstrap an application.

Step 2: Add a scenario

Create a withdrawal feature file under ./features:

Step 3: Generate the glue code

Simply run mvn clean verify`:

This will generate the glue code in the console:

Step 4: Add the glue code to the Step Definitions class

Copy/paste the glue code to the step definitions in the following class.

./src/test/java/cucumber/stepdefs/StepdefsBankAccountWithdrawal.java :

Step 5: Implement every step definition (failing scenario)

Step 6: Implement business code (passing scenario)

Here we can loop with TDD to cover happy unit test cases, unhappy unit test cases, and corner cases, even extreme test cases. Here we still need to keep focus on the scenario. All corner and extreme test cases must be surrounding that specific scenario. Once all unit tests passed, we can make the scenario pass. Then we can continue with another scenario.

Living Documentation

Once the business code is implemented to satisfy the business requirement, simply run this command mvn clean verify` again to execute again the tests.

Now a report is generated under ./target/cucumber/cucumber-html-reports/overview-features.html. Open it with a browser to see the results and you should see this:

That is what we call a living documentation. The approach “Specification by examples” aims to describe business requirement using concrete examples. And it comes with a living documentation as a result, examples of behavior becomes the documentation per se. They are also promoted into automated tests. Whenever a test fails, it indicates that the documentation is no longer in sync with the code so it must be fixed as soon as possible. If the documentation has to evolve because the business changes then the code will evolves too, as they are glued together.

Wrap up

BDD emphasizes on the three steps of first, discover the business requirements by the 3 amigos in a workshop discussing together using a common language (dictionary of business vocabulary). The discussion are based on examples to ease the understanding. Then they formulate their understanding by writing down those examples in scenarios. Once scenarios are written, we can use a tool or framework, such as Cucumber, Behat, SpecFlow, JBehave or some other, to convert them into automated tests.

Testers can use these scenarios as a basis of their tests, and the developers can use them as a basis of their automated tests. And once these automated tests driven through, they are run and passing, then reports are generated against the scenarios.

By having all of these reports automatically generated and scenarios living side by side to the code, and along with all the history of change, we are closer to 100% sure they are up to date all the time. So we also have the traceability, because any change to scenarios is historised the same way as the code change.

Write Medium in Markdown? Try Markdium!

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Kong To
Kong To

Written by Kong To

Architect, Engineer, Developer, Code, Code Crafter... whatever but code quality matters

No responses yet

Write a response