The difference between TDD and BDD
TDD vs BDD
Exactly what’s the difference, and what are the pros and cons of each?
Recently, we discussed what the differences are between acceptance test driven development and behaviour driven development, and clarified how ATDD and BDD fit together. If you haven’t already read it, you can do so here, but fundamentally the message was that ATDD is an activity that exists within the BDD process. Specifically, ATDD can be used as part of the outside in development approach as shown below:
ATDD acts as the ‘outer wheel’ in the model:
ATDD takes the examples captured in Agile team discussions, using a Gherkin format;
ATDD creates failing automation code; and
ATDD writes production code to make the automated example pass
However, we’ve yet to discuss the inner wheel which is test driven development.
Unfortunately, a lot of discussions around TDD get confused. Teams identify TDD and testing as being one and the same, which gets even more confounding when BDD is brought into the mix. So it’s worth taking some time to discuss:
What TDD is;
The value of TDD;
How TDD differs from testing per se; and
The role of TDD within the BDD process.
TDD isn’t about testing
Test-driven development focuses on guiding developers through a different process to ATDD:
TDD helps the developer think about how a consumer - be it a user or another component - will use a specific function;
Based on the decision the developer makes about how that function will work they create a small unit test to demonstrate that interaction; and then
The developer writes the production code to make that unit test pass
The developer can then refactor their code and run the unit test to ensure the refactor didn’t break anything
Unlike ATDD, TDD is focused on individual functions that when combined will make up a feature (usually across multiple technologies). ATDD is focused on the final feature that is created.
Developers adopt the TDD approach for various reasons, with benefits as outlined below:
TDD encourages better design of production code, making it easier to create dry, or reusable, code;
TDD increases the testability of the product which is beneficial to the whole team; and
TDD gives quick feedback to developers when they refactor their code to make it cleaner, preventing them from breaking existing functions during the refactor phase
So, already we can see that TDD isn’t about testing. Testing focuses on learning as much as possible about a product, service, component or function, and then sharing those learnings with others in the team to help them make informed decisions. TDD has noticeably different outputs to testing activities, but the use of the word ‘test’ within ‘test driven development’ unfortunately results in some people making incorrect assumptions.
If we practise TDD, then no other testing is required
This is simply not true, and can be a dangerous assumption to make! Testing consists of many activities, ranging from testing ideas to assessing risks, then testing for each of them. Additionally, it’s a fallacy that unit tests resulting from TDD give us a full picture of how our products behave.
If TDD is about testing, we need to create unit tests for every test idea and code pathway
This results in a lot of noise for developers and reduces the benefits of TDD. A developer practising a sound TDD approach will create just enough tests to create the feature they are working on. That way they can develop quickly, whilst safely getting useful feedback on what they are creating.
The term ‘test’ is used in test driven development because TDD uses test framework tools (for example Cucumber, Behat, SpecFlow), but TDD uses them in a very specific way which may not have been the intention when the tools were first created. Simply because developers use test framework tools doesn’t necessarily mean they are doing ‘testing’. Just like when you use a screwdriver to open a can of paint or scrape a tough material off a surface, beyond the original purpose of the tool to screw in a screw.
TDD as part of outside in development
As we saw on the outside in development model, TDD is the ‘inner wheel’ of the approach. Once a Gherkin example has been captured from a discussion and then connected to failing automation code, a developer can begin the TDD, or ‘inner ‘wheel’, of outside in development.
With a failing Gherkin example being used as an indicator of when the developer has finished writing enough production code to meet the business's expectations, a developer can then focus on how they are going to create that production code in the ‘inner wheel’. They will cycle through the TDD approach of fail, pass and refactor many times, creating tests for specific functions, and then the production code to make it pass. Once enough units/functions have been created, eventually the ‘outer wheel’ will go green.
In outside in development we follow this common pattern:
ATDD, uses automated examples to guide us towards building the right thing
TDD uses unit tests to guides us towards building it right
That said, TDD isn’t necessarily tied to the outside in development approach. There are teams that carry out TDD who don’t rely on examples that have been identified and captured via collaborative discussion (the key to BDD). However, without those captured examples there are added difficulties in appreciating where to start, and knowing when enough is enough and the feature has been delivered.
TDD and BDD
As we’ve demonstrated, TDD can be used as part of the outside in development process and this, combined with conversations, collaboration and automated examples, is what we know as behaviour driven development (BDD). The TDD process can be triggered by the shared understanding of what needs to be delivered, and it’s an approach that doesn’t stifle the developers’ creativity and problem-solving skills.
The outside in development process can be regarded as guide rails on a bowling alley - preventing you from going in the gutter, but giving you enough space to hit a single pin or even score a strike!
You may also like…