Behavior Driven Development (BDD) was first introduced by Dan North as a way to explain Test Driven Development to some customers who needed to apply TDD in their project (see [1] for details). It is a set of collaboration practices designed to help build the right software and to provide real value for the users (in contrast to its better-known brother, Test Driven Development, whose main goal is building the software right).
BDD proposes an approach for minimizing the inherent misunderstanding which arises when the information is passed from one stage to another stage of the software development process (from client to business analysts, then to programmers and testers). It is accomplished by defining real examples as a result of the collaboration of all stakeholders involved in the project.
BDD is not an integral software development methodology on its own (it does not try to address all the areas of this domain), so it should be supported by other methodologies, like Agile, Test Driven Development or Domain Driven Development.
"BDD practitioners use conversations around concrete examples of system behaviour to help understand how features will provide value to the business. BDD encourages business analysts, software developers, and testers to collaborate more closely by enabling them to express requirements in a more testable way, in a form that both the development team and business stakeholders can easily understand. BDD tools can help turn these requirements into automated tests that help guide the developer, verify the feature, and document what the application does." BDD in Action
I selected three benefits which result from adopting BDD practices, because I think these are the most important points to be taken into account when considering the adoption of BDD in a project.
Shared understanding of the project's functionalities across all team members
All team members are involved in the development of a new feature right from the beginning. Business analysts, developers and testers collaborate with the users in order to understand the business value added by the feature in the project, and the details involved in implementing the new feature. As a result of this collaboration, a set of examples are defined in a semi-structured format. These examples will form the acceptance criteria for the feature.
Most of the documentation you find in a project is outdated, as the focus is more on adding new functionalities than to update the documentation according to the last version of the code. It would require a lot of discipline from team members' part to keep track of every code change, and, even if this were possible, it does not guarantee that the specifications will describe how the application is supposed to work, rather than how it actually works. In order to overcome this issue, BDD proposes to translate the examples agreed by the team into automated tests (or executable specifications, as they are often named) using some specialized tools, such as JBehave and Cucumber. These tests provide a live documentation for the actual version of the code. In this way, there is no possibility to have an outdated version of the specification: when either the examples or the code is changed, the tests will fail providing a feedback that something should be updated.
Given the fact that the examples describing a feature are automated, by simply running the tests, it can be demonstrated that the code is doing exactly what the users are expecting it to do. The results of the test executions could be visualized in a reporting format (many tools have the capability of generating reports in HTML format) which provide useful information about the features that are completed or in progress. Moreover, the examples could be easily analyzed by non-technical people.
In this section, I will try to give you a basic understanding of the BDD process, by following a real world example. It is not going to be a complete example and, if you need to dig deeper into this subject, please refer to the other tutorials on BDD which you can easily find on the Internet.
As a high level description, BDD consists of the following steps:
This step is done by the customer himself (or the one who needs the application), as he knows in which way the application will help its users. At this stage, the stakeholders try to identify the Whys or Whats of the project (Why do you need to build it? or What are you trying to accomplish through this application?) which will support finding the Hows at a later stage (How are you going to meet your customer's expectations?).
For example, one such goal for an online shop application could be:
Provide the users with the easiest way to reach the products they need.
For every business goal defined at the previous step, a set of features will be identified in order to accomplish those goals. This should be done as collaboration between both technical and non-technical team members. A feature meeting the proposed goal could be:
In order to find the products I need in an easy way, ….
As a user, ….
I want to be able to search the products by category ….
The BDD practitioners recommend putting the business goal as the first statement in a feature description in order to make clear what is needed to be accomplished.
Neither this step nor the previous one is a one-time job. Due to many reasons, it is possible that the business goals will change and that, during the implementation, you will find some better ways to accomplish the same goals.
In order to better understand what needs to be implemented for a feature, the team members will specify some examples of real use cases. These examples will form the acceptance tests for the feature and will guide the implementation.
For specifying the examples, a semi-formal format will be used, for example:
| Name | Description | Category |
| USB | USB cable | Connectors |
| Mouse | Wireless Mouse | Peripheral devices |
|Keyboard |Wireless Keyboard |Peripheral devices |
|HDMI |HDMI cable | Connectors |
When a user searches all the products in the "Peripheral devices" category
Then the following products are returned:
|Name |Description |
|Mouse |Wireless Mouse |
|Keyboard |Wireless Keyboard |
This Given-When-Then format is called Gherkin, and it offers a simple and expressive way of specifying an example. Moreover, this format could easily be translated into automated tests.
To show how the previous claim is translated into automated tests, I will use JBehave, which is a Java framework for BDD. JBehave matches a statement from the example (or scenario, in JBehave lingo), and calls a method corresponding to it, where the actual test steps are implemented. JBehave recognizes many keywords, such as Given, When, Then, And and But, and could be integrated with different other testing tools in order to test your application at different levels (for example, you can use Selenium for testing the interaction with the web UI).
As an example, here is a part of a test class which automates the when statement from the scenario:
List products = null;
@When("a user searches all the products in the "$categoryName"
category")
public void whenAUserSearchesAllTheProductsInACategory(
@Named("categoryName")final String categoryName){
products = productService.searchByCategory(categoryName);
}
As you can notice in the example above, the matching is done on the whole statement. The category name was parametrized (using a $ before the parameter name in the statement) which allows me to change its value as needed or provide a set of values for which I expect the same behavior.
The first iteration will result in a failing test, but it will guide us in implementing the functionality as expected. After executing these tests, an execution report could be generated in a human readable format. Many teams have automated the deployment of these reports in order to make them accessible for all stakeholders in a fashionable way. The reports provide many useful details, including information about the progress on implementing a feature, features which are still waiting to be implemented and features which have been broken by the latest code changes.
At the unit test level, BDD recommends writing low level specifications (in contrast with the high level specifications - acceptance tests-, which are accessible by non-developers too) to help developers understand what the role of the corresponding tested class is. It is recommended that all unit tests start with the word should, followed by the expected action or result.
@Test
public void shouldReturnAllProductsForCategory_withValidCategoryName(){
//Given
final String categoryName = randomCategoryName();
final List products = randomListOfProducts();
BDDMockito.given(productRepositoryMock.findByCategory(categoryName ))
.willReturn(products);
//When
final List result = productService
.searchByCategory(categoryName);
//Then
MatcherAssert.assertThat(result, Matchers.equalTo(products));
}
For this unit test, I used the testing libraries BDDMockito (an adapter of the Mockito mocking library which lets you define the mocks in a BDD style) and Hamcrest (which is a more human readable assertion library). The same could also be accomplished with basic JUnit tests, just by separating the test according to the Given-When-Then statements.
After completing these steps you should have some automated examples and a feature working as expected.
As usual, the theory does not always have an exact application in practice. It needs to be adapted to your project's requirements. In the next lines, I'll try to give you an idea of how BDD fits into our development process.
The development of a new feature starts with the product owner coming with an informal description of the functionality that needs to be implemented. This document is meant to be just a starting point so that all team members have a basic understanding of what needs to be implemented and, more importantly, why it is going to be implemented.
All team members take part in a meeting where the feature is discussed in more detail. As a prerequisite for this meeting, every member should read the specification in order to identify possible constraints and areas that need more explanations. During this meeting, some Gherkin examples are sketched out and the team should now have a good understanding of what needs to be implemented and in which way it is going to help the users.
After the meeting, the testers will define some relevant examples for this feature. The scenarios are defined in a story file which will be translated in automated tests at a later time. All team members collaborate around these examples in order to refine them and make sure they catch the most important use cases of the new functionality. The collaboration is done through a Pull Request opened in Github and all the members involved in developing this feature comment on it.
At this step, the implementation can start. As the implementation evolves, some of the examples are translated into automated tests. Only one or two happy path examples will be automated at the end of the first iteration of the implementation.
The feature is canary released and, if the stakeholders are satisfied with the implementation and the feature proves to be stable after being in execution for a few weeks, then the rest of the examples are automated too and the feature is considered done. Otherwise, changes in implementation and scenarios could occur.
In this paper, we have saw that BDD offers a set of practices for delivering the right software, as a result of the collaboration of all the team members. The main benefits of applying BDD in your project include: all team members have the same understanding of the project's functionality; easier integration in the project for new members; BDD offers a way for tracking the progress and demonstrating that the implementation is correct; the documentation always reflects the current state of the code.
Furthermore, an example is given for how BDD is applied when developing a new feature. As these practices are more like guidelines, I gave a short description for how BDD practices are applied in a real project.
Even if you think this is an interesting approach for software development and you would like to use BDD in your project, I would recommend doing a thorough analysis before taking a decision. First, you have to identify the problems you try to address and, if some of these problems match the ones detailed in this article, BDD could be considered an option. But that is not enough, because BDD has some requirements in order to be applied correctly. For example, if your project does not allow a frequent communication with your customers you won't be able to get the best out of this approach. In addition, if your requirements are simple enough and everybody has a good understanding of what needs to be implemented, it would be a waste of time to define and automate some examples. In conclusion, as it is always the case, you should carefully choose the right tools that can help you achieve your goals.