Introduction to Behaviour Driven Development (BDD)

Lately, I've been very interested in ways of improving software development, quality, and delivery on my team. Looking for ways to tackle common pitfalls in Agile, I've come across something called Behaviour Driven Development (BDD).

What is BDD?

Behavior-driven development is all about collaboration between teams. More specifically, between business people and technical people. But Why?

Well, business people understand user scenarios, user modules, and how users interact with our applications, while technical people (ie dev, QA) are the ones in charge of doing the actual implementation. As you may have experienced, there is usually a gap in the understanding between these 2 teams.

Behaviour Driven Development is a set of practices that allows software development teams to work in a way that closes the gap between business and technical people, by:

  • encouraging collaboration across roles to build a shared understanding of the desired behavior of the system.
  • producing system documentation that guides the development and is automatically checked against the system's behavior.
  • working in rapid, small iterations to increase feedback and the flow of value.

How does BDD work?

Basically, it consists of doing 3 things over and over again:

  1. First, you take a small upcoming change to the system, like a user story, and have a conversation to explore, discover and agree on the desired behavior of the system, by using concrete examples.
  2. Then, we document those examples in a way that could be automated and check for agreement.
  3. Finally, we get to code and implement the behavior described by each documented example, starting with a failing automated test that will guide the development.

These 3 practices/phases are called Discovery, Formulation, and Automation.

Discovery (What it could do)

  • Documentation and automated tests are nice side-effects of BDD
  • Real goal is valuable, working software.
  • The fastest way to get there is through conversations between the people involved in imagining and delivering the software.
  • Have the right conversations at the right time.
  • Minimize the amount of time spent in meetings & maximize the amount of valuable code you produce.

Discovery workshops

Screen Shot 2021-10-18 at 09.20.31.png

Note: You may think you are already doing this, through backlog grooming, refinement, planning poker sessions, or similar meetings depending upon your Agile framework, but we will later see the problems with those and how a Discovery Workshop can actually be shorter and much more productive.

Formulation (What it should do)

  • We can now formulate each example as structured documentation.
  • We use a medium (ie Gherkin) that can be read by both humans and computers
  • Get feedback from the whole team about our shared vision
  • We’ll be able to automate these examples to guide our development of the implementation.

Gherkin example

Feature: Process refunds
Scenario: Customer has their receipt
    Given the customer has purchased a kettle for $10
    And they have their receipt
    When the sales assistant processes the refund
    Then the stock inventory for kettles is incremented by 1
    And the customer’s card is credited with $10

Automation (What it actually does)

  • Now, we can use our executable specification to guide our development.
  • Taking one example at a time, we automate it by connecting it to the system as a test.
  • The test fails because we have not implemented the behavior it describes yet.
  • Now we develop the implementation code, using lower-level examples of the behavior of internal system components to guide us as required (micro-tests or unit-tests) a la TDD.

For the automation phase, we make use of automation tools that can understand the specification language and transform it into automated specifications.

With this, developers can then use this automated specification to guide the application development. Some of these tools are Cucumber, JBehave, Behat, and Specflow, among others. These tools allow mapping specific lines from each scenario to an instruction that will actually execute it in the app. These mappings are called Step definitions, which can explore in more detail here.

There's often some confusion as to who should write the Gherkin scenarios and who should write the step definitions. This is a good explanation of this topic.

However, as recommended by Cucumber guys, as the team is building the shared understanding and ubiquitous language, the Product Owner/manager should be involved in the writing of the gherkin scenarios along with a developer and a tester.

After the team is confident with the understanding of the domain language, they can start doing the scenarios themselves without the Product person, and just do a sanity check after they are done to confirm we have captured the examples correctly in the formulated documentation.

The whole BDD process:

Screen Shot 2021-10-16 at 17.38.52.png

As you can see, each phase has an objective and outputs that power the next phase. So, for the Discovery phase, we want to explore and discuss how the system should behave, and the outcome of it is an agreed behavior of the system through concrete examples.

Next, for the Formulation phase, we grab those concrete examples from the discovery phase and we formulate them in a way that can be automated, which has the outcome of a set of documented examples and acceptance tests.

Finally, in the Automation phase we do the coding as per the documented examples, to implement agreed system behavior. However, we do this by first creating an automated test (taking one example at a time) to guide the development.

Living Documentation

Over time, the documented examples become an asset that enables the team to continue confidently and rapidly making changes to the system. This is called Living Documentation because:

  1. The code reflects the documentation.
  2. The documentation reflects the team's shared understanding of what the code does.

This shared understanding and the living documentation are constantly evolving and are kept up to date with the actual system behavior, as the implementation is guided by them.

What this means is that the documentation (the formulated gherkin scenarios) is always up to date with what the system actually does. And if we have automated this documentation, using a tool like Cucumber, we would know very fast when something is not working as expected, since the automated tests would instantly fail if the system does not behave as the formulated Gherkin scenarios describe.

So, these formulated scenarios act as the single source of truth for all teams to have a shared understanding of how the system should behave, and for any new team member or external person to easily grasp how the system currently behaves, without having to dig into the source code or out of date documentation/Jira tickets.

Furthermore, there are several tools that can automatically generate a beautiful documentation web page based on those scenarios and will generate useful reports on the automated runs. You can check what Serenity BDD does, for example.

Where does BDD come from?

Our traditional approach to software development has been TLD (Test Last Development), where you first do the coding and afterwards you create the tests. You could call this tests driven by code.

However, there is another approach call TDD (Test Driven Development) where you create the tests first of what you want the system to do (which will fail right away of course) and then you do the coding for those tests to pass, effectively guiding the coding through tests, with several benefits that come with it.

Quick TDD overview

I will (hopefully) do a more in-depth series on TDD in the coming months, as it is a topic that I'm very very interested in and trying to push me and my team to learn and build a habit for, but for now, let's quickly explain what it is so we can see how it all fits together.

As already said above, TDD stands for Test-Driven Development. A good, short definition of it can be grabbed from this IBM article :

Test-driven development reverses traditional development and testing. So, instead of writing your code first and then retroactively fitting a test to validate the piece of code you just wrote, test-driven development dictates that you write the test first and then implement code changes until your code passes the test you already wrote.

In TDD, you write your unit test first, watch it fail, and then implement code changes until the test passes. Sounds backwards, right? But the code you produce when you use this testing methodology is cleaner and less prone to breaking in the long run.

A unit test is simply a test that covers a small portion of logic, like an algorithm, for example. Unit tests should be deterministic. When I say “deterministic” I mean that unit tests should never have side-effects like calls to external APIs that deliver random or changing data. Instead, you’d use mock data in place of data that could potentially change over time.

TDD consists of 5 steps and is implemented through the red-green-refactor workflow:

Screen Shot 2021-10-17 at 15.47.20.png

  1. Read, understand, and process the feature or bug request.
  2. Translate the requirement by writing a unit test. If you have hot reloading set up, the unit test will run and fail as no code is implemented yet.
  3. Write and implement the code that fulfills the requirement. Run all tests and they should pass, if not repeat this step.
  4. Clean up your code by refactoring.
  5. Rinse and repeat.

Note: It is important to note that TDD is not about testing. Unit testing is, but TDD is all about design. Simply put: The design of your code is highly impacted by following the TDD methodology. Your code will most likely follow good code patterns to make it testable from the get-go, instead of figuring out after the fact how to properly test your code.

TDD => BDD

Well, BDD can be seen as an evolution of TDD. While code is driven by tests in the same way (we write tests first and then the application code to make them pass), there are some key differences:

  • Tests are explained as a behavior of the application
  • More user-focused
  • BDD uses User Stories for every feature to be tested.
  • BDD uses human-readable descriptions of user requirements as the basis for tests
  • Tests (also called executable specifications) are written in a shared language (ie Gherkin) which improves communication between tech and non-tech teams and stakeholders.

As explained by the creator of BDD, Dan North back in 2006, he came up with it as a response to the challenges and pitfalls he experienced while teaching and training teams into using TDD.

I had a problem. While using and teaching agile practices like test-driven development (TDD) on projects in different environments, I kept coming across the same confusion and misunderstandings. Programmers wanted to know where to start, what to test and what not to test, how much to test in one go, what to call their tests, and how to understand why a test fails.

So, as you can see, BDD focuses more on behavior, user scenarios, and acceptance tests, while TDD is more developer, unit test focused. In the end, both cycles are intertwined, as you start from a failing scenario test in the overarching BDD cycle, and then go deeper, following the inner TDD cycle to make smaller/unit tests pass, which in the end will fulfill the scenario test written.

Screen Shot 2021-10-17 at 17.57.42.png

Key Benefits of BDD

  • All development work can be traced back directly to business objectives.
  • Software development meets the user's needs. Satisfied users = good business.
  • Efficient prioritization – business-critical features are delivered first.
  • All parties have a shared understanding of the project and can be involved in the communication.
  • A shared language ensures everyone (technical or not) has thorough visibility into the project’s progression.
  • Resulting software design that matches existing and supports upcoming business needs.
  • Improved quality code reducing costs of maintenance and minimizing project risk.

BDD and Agile

BDD does not replace an existing agile process. You actually require an agile process to be in place to do BDD. So, it actually enhances it. You can think of it as a set of plugins that will make your team more able to deliver on the promises of agile: Timely, reliable releases of working software that meets the organization’s evolving needs.

What we want is to work in rapid iterations, and quickly respond to feedback from our users, while doing only the minimal work necessary to meet those needs. Thus, BDD encourages working in small, rapid iterations, breaking down users' problems into smaller pieces that can flow through our development process as quickly as possible.

A nice post on how BDD supports agile can be found here, but this gist will help illustrate the main selling point of BDD in Agile:

Behaviour-Driven Development was carefully developed to support agile development in the software industry. This is because agile cannot be fully deployed if the testing process still follows a traditional methodology.

Let's imagine an organization works in a traditional waterfall approach, where testing starts once the development work has been completed. It doesn’t allow for alterations or changes until the testing phase has been finalized which slows down the development process considerably.

So, this organization then decides that they need to go to market faster and accelerate releases. After some consideration, they decide to go agile through the means of sprints, scrum, or the like.

However, after some time, they realize that testing has become the bottleneck of their agile efforts. QA struggles to keep up with this accelerated pace. They finally decide to seek continuous testing through test automation.

Even though this decision will most probably improve the current state of the project in some way or another, two key issues will arise throughout this last agile implementation to the software development process:

  1. How aligned is development and QA at this development speed?

  2. How can they make sure that they are building what the customer wants?

The answer to both of these questions have a common denominator: Collaboration

And BDD facilitates exactly that!

How can BDD improve your Agile workflow?

Let's see how bringing BDD practices into your agile workflow might look like. First, let's illustrate how a traditional agile workflow goes.

Screen Shot 2021-10-17 at 13.11.03.png

Normally, during the requirements gathering and creation of user stories (steps 1 and 2 of the workflow) exclude dev and QA perspectives. They are not involved in that process of discussion, creation, and exemplification and are just handed user stories.

As a result, on step 3, both dev and QA start to work in their own silos, meaning that there's no shared understanding between both on the requirements of what's going to be implemented and tested for, and what Product actually expects from the system.

Even though some Agile teams will have different meetings for going through the upcoming backlog, like backlog grooming, refinement, planning poker sessions, or similar meetings depending upon your Agile framework, these are often unstructured, boring, long and team members will not go deep into actually getting to a shared understanding of the requirements of each user story. They may even exclude people with the actual know-how of the domain (ie Product people).

This lack of communication and misunderstanding is what BDD is meant to tackle.

Now, let's see how an implemented BDD workflow looks like:

Screen Shot 2021-10-17 at 13.17.34.png

It starts with the same stage where the Business team discusses the requirements, needs, and changes that they need in the application.

Afterwards, the Business representative (typically a Product Owner) will gather with representatives of the Development and Testing teams, in what we call 3 amigos meeting to discuss the requirements, the specific user stories, and the examples that define the user behavior until an agreement is achieved.

Later on, the examples are documented in a specification language (like Gherkin) that converts the examples into documentation that can be used by business and technical teams, as well to implement automation, guide development, and perform regression testing.

So, you can see that the main advantage here is that, right after the requirements gathering is done, there is a complete communication and collaboration between all the involved teams, sharing a common understanding and a single source of truth: the documented examples for the agreed behavior of the system. So all teams can refer to it and work based on it, which should prevent misunderstandings and rework to a high degree.

So, let's see how it fits and compares into a Sprint workflow with a traditional approach:

Screen Shot 2021-10-17 at 13.22.29.png

A sprint is a short, time-boxed period where the team works to complete a set amount of work.

Some activities are done before the sprint and others during the sprint.

In the traditional approach, things start with the Business Analyst or Product Owner gathering the requirements and writing user stories and acceptance criteria based on them.

Afterwards, user stories will be committed to the sprint and the sprint starts.

During the sprint, the Dev team will start developing the code and the test team will start creating test cases. Afterwards, tests will be automated and executed and if there are bugs, they will be fixed and re-tested.

On the other hand, in a BDD workflow, even though it starts the same way with the BA/PO gathering requirements, writing user stories and initial examples, we also perform discovery workshops (3 amigos meetings) to discuss and explore the user stories and examples and finally, behavior is agreed upon.

Afterwards, we can decide which user stories will be worked on in the sprint, based on the duration and velocity. All the team members can decide this, with greater knowledge of what's involved in each user story.

Also, the agreed and selected examples are documented using a specification language so they can serve as a single source of truth for all teams.

It is after all this that the sprint starts and dev and QA teams can work in parallels based on a single source of truth.

Conclusion

We have seen what is BDD, the phases it consists of, and how it fits into an agile workflow.

Of course, BDD has a learning curve for development teams. Although defect rates will drop substantially very early in the process, productivity often suffers as the team gets the hang of it. A nice article about BDD adoption, tips and useful metrics to keep track can be found here, which in itself links to other very useful resources.

In my next post, I will dig deeper into the discovery phase, and focus on a specific technique called Example Mapping, to perform the discovery workshops in a fun, useful way that may render your normal backlog groomings obsolete.

Also, I recommend you buy and read the BDD Books. They are great resources to learn and start applying and maturing BDD techniques in your teams, based on two well-known BDD experts' experiences.

References:

dannorth.net/introducing-bdd

agile-doctor.com/2012/03/06/10-reasons-why-..

leapwork.com/blog/how-does-behavior-driven-..

developer.ibm.com/articles/5-steps-of-test-..

cucumber.io/docs/bdd/who-does-what

youtube.com/watch?v=cq_3wPnaX-w&list=PL..