This article addresses the main differences between Behavior Driven Development (BDD) and Test-Driven Development (TDD) with real-world examples and code snippets. It is a common misconception 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 Owners. 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 is taken from the founder of BDD Dan North’s article:
Sample BDDScenario: 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 that 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. 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 and 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 (mainly the three amigos), 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 writes scripts or uses a scriptless automation tool such as NoCodeBDD to automate the scenarios. The developer implements the code, which should satisfy the agreed scenarios.
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
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 artifacts – i.e., Features, Scenarios, and Steps – derived via Behavior Driven Development are developed and maintained by the entire team. 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 ongoing 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 automate 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 the 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 UI, API, Database, 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
The following table summaries the differences discussed above
BDD Scenarios are derived through collaboration between team members
Implemented by developers
BDD Scenarios are written in Natural Language
Written in a programming language
Created and maintained by the entire team
Created and maintained by developers
Tests the end-to-end behavior of the application
Tests are written for individual function
BDD vs TDD – Summary
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 positive 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 effective collaboration. By collaborating effectively, the issues that may come later in the software life cycle are addressed upfront, thus reducing any rework. We have put together a video that explains how a very effective collaboration technique called OOPSI, which could help you to derive scenarios that achieve the highest business outcome.
These agreed scenarios are used as a base for testing and development. QA then uses the scenarios and starts implementing automation scripts. 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
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, any interface with the application code should be mocked, so the Unit Tests could be run on their own without having any dependency on the server, database or any interface including UI and API.
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 and costs.