Agile software development is an innovative approach to software development that introduces iterative and incremental development processes to make gains on speed and flexibility. As a client-centric model, Agile development focuses on continuously incorporating feedback to ensure the product is aligned with the desired outcome at every stage of development. This feedback comes through continuous testing.
In Agile, testing happens early and is continuous, tightly woven with development. So it makes sense that there are many structured methodologies about how to approach development with this testing-focused approach.
This guide will compare the most popular Agile testing methodologies, including Test-Driven Development (TDD), Behavior Driven Development (BDD), and Acceptance Test-Driven Development (ATDD).
What is Test-Driven Development (TDD)?
Test-driven development (TDD) approaches development by converting the software requirements into unit test cases before the software is developed. A unit test case is a set of actions that verify a specific feature or functionality. Since TDD pre-defines the test cases before development begins, it is often referred to as test-driven design.
Unlike traditional software development, where code is written and subsequent test cases are created and tested, TDD develops test cases before any code is written, continually testing code against the test cases throughout the iterative development process through the “red green refactor loop” until you have a complete unit.
TDD developers create test cases of the smallest possible unit of functionality, allowing for each unit to be tested and to pass before other units are added into the design. As a result, TDD often encourages very short development cycles.
In TDD, there are three rules or “laws,” as developed by Robert C Martin (“Uncle Bob”), a well-known software developer of the Clean Code book and one of the original authors of the Agile development manifesto. These laws are:
- You must write a failing test before you write any production code.
This law dictates that you write the test before coding, dictating how the code is expected to work.
- You must not write more of a test than is sufficient to fail, or fail to compile.
This law dictates that you test your code at this point of failure, even if it is after only one line of code. The code is incomplete, so it will always fail.
- You must not write more production code than is sufficient to make the currently failing test pass.
This law dictates that you write the bare minimum of code to get to pass, that no code should be written beyond the functionality being tested. On the unit level, this keeps code clean and precise.
The TDD Methodology
Let’s dive deeper into how TDD development works step-by-step:
- Write a test
Write a unit test that passes if the feature’s specifications are met.
- Run the test(s) and watch it fail
Run the tests, validating that code is truly needed for the test to pass. The test has thus failed for expected reasons, ruling out that the test is flawed.
- Write the code
Write the simplest code possible to pass the unit test.
- Test the code
Test against the unit test. Continue this cycle of coding and testing until the unit test passes.
Restructuring the code (changing the factoring) without changing the behavior to improve non-functional attributes. The goal of refactoring is to further improve or simplify the design, structure, or implementation of the software to make it easier to work with or improve its performance without changing the behavior of the functionality.
- Repeat the steps
The unit test process begins again after refactoring to ensure functionality remains and bugs have not been introduced.
To go into the methodology in more depth, TDD looks like:
To give a practical example of how TDD would work, let’s imagine a program whose purpose is to say “yes” if a number is less than or equal to 10 and “no” if it is greater than 10. For this program, the test cases would be:
- Give it the number 1, it should say yes
- Give it the number 10, it should say yes
- Give it the number 11, it should say no
- Give it the number 1232, it should say no
After writing these test cases, code is written to specify that if the number is less than or equal to 10, it should return a “yes.” The code is then run against the test cases, with 1 and 2 passing, 3 and 4 failing. Further code is written; this time, the code is written to specify that if the number is greater than 10 it should return a “no.” You then test all test cases again, with all tests passing. Now, imaging all of this was explained alongside the code as a comment. Refactoring would be the process of removing all this excess text from the code. Testing would then re-assess the functionality of the individual units.
Benefits of Test-Driven Development
TDD forces teams to carefully assess what they are developing and how it will be used. The advantages of test-driven development include:
- Faster development – Since tests are specified at the unit level, developers know exactly what they are doing, helping speed up development.
- Clean code – The result of clarity is well-designed, clean and simple code without over-engineering.
- Clear documentation – The creation of unit tests clearly documents all steps of software development.
- Fewer bugs – Since TDD continually tests each unit, the software has fewer regression defects and bugs overall.
- Tighter code – The continuous review of code to improve efficiencies (refactoring) helps reduce code duplication and improve the organization of the code.
While TDD requires more up-front planning, this investment of time often results in even greater time savings during coding and debugging, helping to improve time to market. From a user perspective, TDD often results in improved performance.
What is Behavior-Driven Development (BDD)?
Behavior-driven development (BDD) is based around the same concepts as TDD, but one step higher, focusing on functional testing of the expected behaviors of an application – hence its name. In this way, BDD is often considered an extension of TDD, helping to test whether or not all the units work together as expected to form a whole application.
BDD creates a functional test (a higher-level test) that creates a requirement that fails because the feature does not exist:
TDD vs BDD? Like with TDD, the BDD development cycle focuses on writing a feature failing test, test prototypes for early failure feedback, and then writing the minimum code to implement and adjust the product until it satisfies the test:
BDD Behavior Definition: Given, When, and Then
The first step of BDD is understanding user behavior by gathering together key stakeholders in business, development, and QA testers to define the user story, which forms the acceptance test:
- As a
Defines the persona (role / actor / stakeholder)
- I want
Defines the problems and wants (features / capabilities) of the persona
- So that
Defines the benefit / yield / aftereffect of including that feature.
The team discusses the user story with concrete examples, ideas and concepts of the requirements and how it should behave in order to move onto capturing those concepts in concrete terms that form the criteria for the acceptance test, created in the following format:
Describes the scenario being tested or the stage of the user to testing (the context)
Describes the action the user performs
Describes the expected system reaction (outcome) to the user action described in ‘when’
What is Gherkin?
Gherkin is a domain-specific language created for writing behavior scenarios in the Given, What, Then syntax. Although it is a programming language, it is often referred to as “business readable” as the “code” is meant to sound like plain language (English or any of over 37 other spoken languages!). The official Gherkin language is maintained by Cucumber (one of the BDD framework tools), although most other BDD frameworks also leverage Gherkin to some extent.
Benefits of Behavior-Driven Development Approach
- Shared understanding – TDD forces a clear articulation of the user story, helps bring clarity to what is being developed and how the criteria of each user story are being met. This clarity often saves both time and money.
- Tests are reusable – Tests can be reused to test behavior over and over.
- Common language – As there are many stakeholders in BDD, the use of non-programming language to describe the tests is very helpful to improve communication and get everyone on the same page.
Which one is better: BDD or TDD? The answer is neither – or both? Each has an important part to play in development, depending on the needs of the project. Can you use BDD and TDD together? Yes! You may use one or both approaches, or mix and match throughout your development.
How does BDD help in SDLC?
SDLC, or the software development life cycle, is a set of defined processes toward software development which, when followed, help develop software quickly and at high quality. The sequential order of the 6 stages of SDLC help ensure foolproof software delivery and keep development on track. A missed step or a step done haphazardly will result in poor software quality – in the same way that skipping steps or changing recipe quantities will impact a baking recipe. The SDLC approach to development is sometimes referred to as a “waterfall” approach, because it approaches development sequentially.
This guide has walked through the relationship of TDD and BDD to the Agile development philosophy, so what does BDD have to do with SDLC? In the traditional “waterfall” approach, testing comes after design and development, but a lack of clear requirements is often the root cause of bugs and product misalignments. BDD concepts can be leveraged to help pre-define requirements in a standard approach, in plain English, to help better define where the product is going to go and allow technical and non-technical teams to collaborate toward those goals.
How to Implement BDD?
In BDD, test scenarios are written in plain language with a description of what the test is and how the test should be run. The easiest way to implement BDD is to leverage a framework tool. Cucumber is the most popular open-source Behavior Driven Development (BDD) testing framework tools, with SpecFlow, Fitnesse, JUnit, and Concordion being other options. Cucumber supports several languages, but primarily Gherkin (see below).
What is Acceptance Test-Driven Development (ATDD)?
Acceptance test-driven development (ATDD) involves diverse stakeholders (customer, development, testing) and plain language to write acceptance tests based on the shared understanding of user story requirements, sharing the same concepts as BDD. However, ATDD works more like TDD, with acceptance tests written before coding.
ATDD acceptance tests are written from the user’s external point of view – an expression of the requirements for the application, in plain language, that can be turned into automated acceptance tests. ATDD can borrow the Given-When-Then syntax of BDD, but the focus with ATDD is on meeting the needs of the user, which is more in tune with the user story than simply focusing on expected behavior.
ATDD vs TDD? In both cases, we set up test cases before development. However, TDD is very technical, written in code, while ATDD defines the requirement of the feature, in plain language. TDD asks the question of “are we building the thing right?” at a granular level, while ATDD asks the question “are we building the right thing?” Success in TDD is based on meeting a functional requirement while success in ATDD is based on meeting client needs.
ATDD vs BDD? While the distinction involves some nuance, BDD is concerned with how a feature behaves while ATDD is focused on defining the requirements of the feature based on the user story before development begins. To follow the above example, BDD would ask, “is the thing behaving as expected?”
Benefits of ATDD
The benefits of ATDD are similar to those of BDD, improving communication and understanding between teams, ultimately reducing time to market and improving code quality.
TDD vs BDD vs ATDD: A Comparison
At this level, what should jump out to you is the level at which each kind of testing is applied. TDD is for unit tests, BDD for functional tests, and ATDD for acceptance tests. Let’s break that comparison down even further.
|Definition||A development technique focused on individual units of a desired feature||A development technique focused on expected behavior||A development technique focused on meeting the needs of the user|
|Participants||Developer||Developers, Customer, QAs||Developers, Customers, QAs|
|Language Used||Written in programming language used for feature development (Eg. Java, Python, etc)||Gherkin / Simple English||Gherkin / Simple English|
|Understanding Tests||Tests written by and for developers||Tests written for anyone to understand||Tests written for anyone to understand|
|Focus||Unit Tests||Understanding Requirements||Writing Acceptance Tests|
|Bugs||Reduced likelihood, easier to track down||Can be more difficult to track compared to TDD||Can be more difficult to track compared to TDD|
|Suitable For||Projects that do not involve end users (server, API, etc)||Projects which are driven by user actions. For eg: eCommerce, app||Projects where customer experiences are important and competition is high, e.g. eCommerce, app|
|Tools Used||JDave, Cucumber, JBehave, Spec Flow, BeanSpec, Gherkin Concordian, FitNesse, Junit, TestNG, NUnit frameworks, Selenium tool (any open source tools)||Gherkin, Dave, Cucumber, RSpec, Behat, Lettuce, JBehave, Specflow, BeanSpec, Concordian, MSpec, Cucumber with Selenium / Serenity||TestNG, FitNesse, EasyB, Spectacular, Concordian, Thucydides, Robot Framework, FIT|
Taking the Next Steps with TDD, BDD and ATDD
Agile development helps create a collaborative user-centric environment that focuses on understanding what users want and ensuring timely and quality product development. Through the TDD, BDD and ATDD frameworks, Agile teams can leverage articulate processes to capture requirements and test them at low-level (unit tests) and high-level (acceptance tests) to ensure a quality application. In the real world, however, organizations face many pressures – competition, time, skill shortages – that make it difficult to make all of this a reality.
At Net Solutions, our customer-centric, Agile approach helps get products to market faster with a competitive advantage. We bring to the table the business, design, development, and QA skills to help you discover & define, design, and deliver mobile and web apps that meet the needs of your business and your customers.
Request Free Consultation
Hire product development experts to bring your ideas to life