This article addresses main differences between Behavior Driven Development (BDD) and Test Driven Development (TDD) with real-world examples and code snippets. It is a common mis-conception that Behavior Driven Development is an extension of Test Driven Development and this article explains how it is different and how both can be used together
What is TDD?
Most developers are familiar with Test Driven Development. If you are not, here’s an excellent short write-up by none other than Martin Fowler. So, in essence, unit tests check the correct implementation of single atomic components in the software. To implement TDD, developers need to know the implementation of the code.
What is BDD?
Behavior Driven Development (BDD), is all about collaboratively deriving scenarios from the requirements as concrete examples by a team’s cross-functional members—mainly the three amigos i.e. Developers, QAs and BA or Product Owner. BDD breaks down the requirement as examples in plain, natural language. The examples explain how the application should work from a customer’s perspective. Here is a simple sample scenario taken from founder of BDD Dan North’s article:
Sample BDD Scenario: Account is in credit Given the account is in credit And the card is valid And the dispenser contains cash When the customer requests cash Then ensure the account is debited And ensure cash is dispensed And ensure the card is returned
The derived scenarios then provide a written document which serves as an agreed contract between the business members and technical members of the team. These derived examples (called Features) are then automated using some specialized tools.
So how is BDD different from TDD? Though both TDD and BDD take a “test first” approach, there are quite a lot of differences between them. They complement each other, and using TDD and BDD improves the efficiency of software delivery and improves software quality. Let’s get to the main differences below.
What is the main difference between BDD and TDD?
One of the pertinent differences between BDD TDD is that BDD is done through collaboration among different members of the team (remember the three amigos from above). Conversely, TDD is implemented by the developer, with no collaboration with other members of the team—namely, other cross-functional members of the team, i.e., QA, BA or the Product Owner. We’ll break it down further below.
Typically BDDs are implemented by these cross-functional members of the team who are involved in implementing the story (e.g., UX Designers), collaborating and analyzing the requirement, and writing different real-world examples as Scenarios. This becomes the working document for the entire team. Once the working document is derived, the QA either writes scripts (most definitely the efficient way) or uses those scenarios to test the implementation. The developer implements the code, which should satisfy the agreed scenarios. Finally, the BA/Product Owner uses the derived Feature/Scenarios to validate that the requirements are implemented correctly.
In TDD, the developer either on his own (or with other developers in a pair/mob programming) writes tests for different functions. Once the tests are written, the developer implements the code for the tests to pass. This approach is called Red, Green, Refactor (RGR). Here is a great article on RGR and how it is done using TDD.
What are the other differences between BDD and TDD?
Following are some of the other differences between BDD and TDD:
- BDD is written in natural language and TDD is written in the programming language in which the system is implemented
- BDD is the team’s responsibility whereas TDD is created and maintained by the developers
- BDD is Black Box Testing and TDD is White Box Testing
- When BDDs are automated, the entire flow of the application is tested. TDD focuses on a Unit of the implemented code
Let’s look at these differences in detail
Natural Language vs Geeky
In BDD, the scenarios are written in natural simple language generally written as real-world examples. Dan North’s article has a great example in which a user’s bank account is overdrawn past the overdraft limit:
Scenario: Account is overdrawn past the overdraft limit
Given the account is overdrawn
And the card is valid
When the customer requests cash
Then ensure a rejection message is displayed
And ensure cash is not dispensed
And ensure the card is returned
As you can see, the scenario is written in plain English. Of course, the same scenario can also be written in any language native to the team. When it comes to automation of this scenario, automation scripts are written for each of the lines (called Steps in BDD) in the scenario. In the case of NoCodeBDD, automation is done without writing any code. One of my other articles on this blog gives an example of such an implementation.
In Test Driven Development (TDD), the unit tests are written in the programming language in which the code is implemented. A sample unit test is given below for a code that is implemented using Java.
As shown above, in TDD the tests are written using a programming language and are not easily understood by different stakeholders.
The Team’s responsibility vs The Dev’s responsibility
The artefacts – i.e., Features, Scenarios and Steps – derived via Behavior Driven Development are developed and maintained by the entire team. The BA/Product Owner is responsible for making sure the derived Scenarios cover the requirements adequately; QA’s/Test Engineer’s responsibility is to make sure the scenarios derived test all of the requirements and the Developer’s responsibility is to make sure the code is implemented correctly as per the derived scenarios. These combined responsibilities have to be maintained throughout the duration of the project for BDD to be effective.
However, in TDD, deriving, writing, and maintaining the Unit tests is the developer’s responsibility alone. In TDD, the developer derives and writes the unit tests before writing the code and writes the code to pass the tests. On an on-going basis, Developers alone are responsible for maintaining the unit tests and making sure the tests always pass against the code that is implemented. In TDD, no other cross-functional team members are involved. A solitary task.
Black Box vs White Box Testing
If you are not familiar with black-box testing and white-box testing, here is an excellent article breaking it down. With black-box testing, the testers don’t have to know the implementation details. However, with white-box testing, the implementation details need to be known to test it.
The testing approach in BDD falls under the definition of black-box testing. To create automated tests or to test the application manually, the user doesn’t have to know the implementation details they could simply pass the required information to test the implementation. For example, when BDD is applied for a Registration functionality that takes a full name, email and password the Step definitions (Scripts that automates Behavior Driven Development) are implemented without knowing the implementation details or the code itself. Using NoCodeBDD – without having to know the implementation details, how the code is implemented and even without knowing in which language the code is implemented, you can automate BDD by providing the information required to call the API, as shown in the following video:
Test-Driven Development (TDD) comes under White-Box testing. Without knowing the implementation details, a user can’t implement Unit tests. If we take the same Registration functionality example, the user has to know the implementation detail to write the test as shown in the GIF below
Behavior vs Unit
As BDDs name suggests , you test the behavior of the application. In other words, using BDD you could test the entire flow of your application. BDD spans more than the implemented code and tests the complete application including any Database, API, MQ or any other interfaces. For example, let’s look at the image below. If the application being developed using BDD is a CRM Application, when automating the scenarios the entire application gets tested from receiving a message from the marketing application and sending a message to the invoicing application, to the message that gets stored in the DB.
However, in a TDD, the developers typically test the unit of the code. When writing Unit Tests, the interfaces are typically mocked. For example, if the code is expected to get results from a database, the database is not actually called since the response from the database is mocked, so only the code is tested. An example given below shows this :
Table of differences
Following table summaries the differences discussed above
|1||BDD Scenarios are derived through collaboration between team members||Implemented by developers|
|2||BDD Scenarios are written in Natural Language||Written in a programming language|
|3||Created and maintained by entire team||Created and maintained by developers|
|4||Black-box testing||White-box testing|
|5||Tests the end to end behavior of the application||Tests are written for individual function|
So which is more advantageous to use in a project? The shortest answer is both. The following section shows how TDD and BDD can be effectively used together in a project to improve project quality and reduce the time to market.
Using BDD and TDD together
TDD should still be followed by developers to improve the code quality and to improve efficiency. In fact, in my experience, TDD improves the speed of delivery. However, BDD is an excellent way of getting the entire team on the same page. It reduces ambiguities in understanding the requirements and improves cross-functional collaboration. As a bonus it allows the team to implement end-to-end test automation.
Let’s take a simple example of a user story and see how both BDD and TDD could be used to improve software quality:
As a credit cardholder, I want to view my credit card statement balance
The first and foremost step in a BDD process is to collaborate between cross-functional members of the team mainly the three amigos. The user requirement is discussed and analyzed in detail and various scenarios, including both happy scenarios and negative scenarios, are derived. The pertinent point here is during this process any ambiguities in the requirement should be discussed – and the key to this is the effective collaboration. By collaborating effectively, the issues that may come later in the software life cycle are addressed upfront, thus reducing any rework.
These agreed scenarios are used as a base for testing and development. QA then uses the scenarios and starts implementing automation scripts. Though manual testing can be used in BDD, the team loses out on one of its major advantages, which is automation. The developer then uses the derived scenarios as a base and implements the code. QA uses the agreed scenarios as a base to test the software and the BA/Product Owner uses the agreed scenarios to view the demo and sign off the story.
Scenario 1: User logs in with right credentials and statement balance is shown
Given user details and statement details are in Database
And user logs in with valid credentials
When statement information is requested by the user
Then statement details should be shown
Scenario 2: User logs in with invalid credentials then statement balance shouldn’t be shown
Given user details and statement details are in Database
And user logs in with invalid credentials
When statement information is requested by the user
Then statement details should not be shown
Let’s assume that the application uses Representational State Transfer (REST) APIs. In Scenario 1, the login functionality is called and the state of the user details is passed from the “Given” step to the next and is used in the “When” step to get the statement information. The transfer of state is explained in the video here
BDD is derived, agreed upon, and maintained by the team collaboratively. These derived scenarios are used as a single source of truth – the team uses the scenarios as a specification to develop and maintain the application. Since the specifications can be automated and executed to check whether the application works per the agreed specification, it is also called executable specifications.
Once the scenarios are derived and the team understands the requirements and is on the same page, the developers implement a solution based on the derived scenarios. When TDD is followed, developers would first write the tests, implement the solution and refactor the code to make it better.
While implementing tests in a TDD, the state is not passed between unit tests. Instead, the state is mocked and any interfaces, in this case, the REST APIs and Database, are mocked.
When implementing BDD and TDD there are bound to be some overlap in the tests. However, as we’ve learned, BDDs and TDDs should be used for different purposes. BDDs are great for collaborating between cross-functional members of the team to arrive at a common understanding of the requirement and TDD is used by developers to implement better design and code. By using both BDD and TDD, not only does the overall application improve, but these practices will save time costs.
Jerome Josephraj is the Founder and CTO of NoCodeBDD. He has more than 20 years of experience in Software Development and have been rolling out Behavior Driven Development for large projects in United Kingdom. He has a strong Java Development Background and have been working as a Technical Consultant. In one of his recent large enterprise projects, he has successfully rolled out Behavior Driven Development consisting of more than 1000 scenarios. He was also the Founder of http://www.campusinteraction.com, a student analytics portal, which was later bought by Preludesys. Based on the previous start-up experience and a strong Behavior Driven Development experience, he founded NoCodeBDD to improve efficiency of rolling out Behavior Driven Development by 10x.