As the name “Test First” suggests, you write a test first before the actual code and keep them running all the time. Well, maybe not the second part explicitly. Yet what if I said to you that it actually means more than that?
Firstly it did originate from this simply meaning. When we hear the word “test”, a majority of us think in the traditional sense of checking (e.g validate the code). This can be the first confusion in its understanding and actual meaning today, for either technical or non-technical folk. If you’re not already aware, the way you think of testing within an agile approach is fundamentally different to the traditional one. But let us leave that for another day.
Then we have all these practices you hear about residing under this Test First banner – TDD, BDD, and ATDD. Are all these practices simply for writing tests first and automation? And what are the differences between all these practices, if any?
The name “Test First” has moved on from its original concept and has a broader meaning now. Over time it has evolved to incorporate the following
- Test Driven Development (TDD)
- Behavioural Driven Development (BDD)
- Ubiquitous Language for acceptance scenarios & specifications e.g. Gherkin
It has moved to enable quality focus on both the product and design by enabling faster feedback loops on several different levels, than simply writing tests first before code.
This is likely the reason in 2011, Gojko Adzi introduce a different name to group all these practices – “Specification by Example“, with a redefined purpose statement “build the product right and building the right product”. And the primary output is being “living documentation” and collaboration and with automated tests being specified as the secondary output.
With people’s first exposure to Test First and the TDD and BDD practices, there is a tendency to think in terms of traditionally testing. This can cause people to go down the wrong rabbit hole and begin automating their tests with an automation tool (e.g. Record and Play).
As with anything context is key, so I have found it useful to briefly explain the journey on how Test First and its associated practices have iteratively evolved to help people understand the meaning of Test First and understand each of the practices purpose, focus, differences, and benefits.
Test-First Programming (est 1999)
The term Test-First Programming (TP) was introduced by Kent Beck in 1999 with his book “Extreme Programming (XP): Explained” and states to write unit tests before programming and keep all of the created tests running at all times. A year later, in 2000, Kent Beck published another book called “Test Driven Development by Example” and explains Test Driven Development (TDD) is a software process and not about writing tests before the code with one more important aspect – refactoring. The following is the sequence given in his book: –
- Add a test
- Run all tests and see if the new test fails
- Write the code
- Run Tests
- Refactor Code
- Repeat
This cycle tends to be referred to as Red-Green-Refactor cycle. But Kent, and others, found that writing the test first had a tremendously positive effect on the software architecture and design of software too:
- Testable
- Decoupled
- Reusable
- Independently Deployable
- Independently Developable
- Independently Reasonable
This influence on software design and architecture became so important, besides the other positive effects, that Beck found it worthwhile to rename it from Test-First Programming to Test-Driven Development.
Test-Driven Development 2.0 (est 2004)
Test Driven Development moved slightly further, from Kent Beck’s original Red-Green-Refactor cycle, with Robert C Martin (aka Uncle Bob) and The Three Laws of Test-Driven Development.
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail, and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
This is sometimes referred to as Test First with baby steps. Check out our Introduction to Test Driven Development video for more info and in action.
Robert C. Martin went even further and focused on a 3rd Law. He discovered an approach called Transformation Priority Premise in that a simple transformation should be preferred. The approach facilitates the programmer doing the simplest possible thing for the purposes of Test-Driven Development by favouring the simpler transformation (from the top of the list) over those further down in the list.
- ({}–>nil) no code at all->code that employs nil
- (nil->constant)
- (constant->constant+) a simple constant to a more complex constant
- (constant->scalar) replacing a constant with a variable or an argument
- (statement->statements) adding more unconditional statements.
- (unconditional->if) splitting the execution path
- (scalar->array)
- (array->container)
- (statement->recursion)
- (if->while)
- (expression->function) replacing an expression with a function or algorithm
- (variable->assignment) replacing the value of a variable.
He goes on to suggest that we should amend the Red-Green-Refactor cycle of TDD with the following provisions
- When passing a test, prefer higher priority transformations.
- When posing a test choose one that can be passed with higher priority transformations.
- When an implementation seems to require a low priority transformation, backtrack to see if there is a simpler test to pass.
And states if you follow these rules correctly then you should find
As the test get more specific, the code gets more generic
Behaviour-Driven Development (est 2004)
Behaviour Driven Development was developed by Dan North in response to helping his colleagues to learn TDD. He found: –
- “Behaviour” is a more useful word than “test” – people’s misunderstanding about TDD always came back the word “test”
- Test method names should be a sentence and the word “test” can be stripped out
- A simple sentence template keeps test method focused. The class test method should do something & only that thing
- An expressive test name is helpful when a test fails
In 2003, Dan North created the JBehave framework to replace Junit to remove any reference to testing and replace a testing vocabulary around a behave one.
In 2004, the next discovery for Dan was the concept of business value and why we write software. He found that you could use his framework to help the team focus on feature behaviour and that missing requirements are behaviour too. Around this time Eric Evans also published his bestselling book Domain-Driven Design where he describes the concept of modelling a system using a ubiquitous language based on business domain, so that the business vocabulary permeates right into the codebase. Dan and his colleagues used a similar concept to come up with defining a ubiquitous language for the analytics process itself, hence where the Given, When, Then for acceptance criteria came.
Since then many people have developed other BDD frameworks and then finally began framing BDD as a communication and collaboration framework for developers, QA and business in a software project. During the “Agile specification, BDD, and Testing eXchange” in November 2009 in London, Dan North gave the following description of BDD:
BDD is a second-generation, outside-in, pull-based, multiple-stakeholder, high automation, agile methodology. It describes a cycle of interactions with well-defined outputs, resulting in the delivery of working, tested software that matters.
During an interview with Dan North at GOTO Conference in 2013, Liz Keogh defines BDD as:
It’s using examples to talk through how an application behaves. And having conversations about those examples
Since Dan North’s first java based BDD framework of JBehave, the leading BDD framework is Cucumber and reads executable specifications written in plain text that follows some base rules called Gherkin. It is used by the majority of languages & you can test about anything with it and build out test frameworks for your systems and products. It also works well with other tools to enable testing of APIs, Browsers, and other system endpoints.
What about Acceptance Test Driven Development?
Acceptance Test Driven Development or ATDD is where the entire team collaborates to define the acceptance criteria before implementation. It drives acceptance testing rather than unit testing by facilitating a detailed readable description of the system’s function through proper examples and other necessary information. And with a focus on n an outside-in development approach. Sounds familiar?
Most of the time, BDD and ATDD are used interchangeably. The ATDD approach can be implemented using the Given-When-Then format and use BDD framework tools. But also we can use BDD frameworks for the TDD approach. Confused yet?
Personally, we used ATDD for 2 years before becoming aware of the term BDD. When we first heard the term, it was confusing & why is it different to what we were doing. Perhaps because we already practising Domain Driven Development, collaborating and using a test framework with a Given-When-Then option. And the “Acceptance Tests” occurred at the end to end tests but also at the component, integration and unit tests too.
Reading John Ferguson Smart’s book “BDD in Action“, would have cleared that confusion far quicker for us if it had been around at the time. It would have helped us considerable especially the sections “Coding the BDD way” & “Taking BDD further”. Highly recommend reading.
Summary
In essence, the approach has evolved to be all about the conversation first between the business and development team to build the right product and developed using an outside-in workflow to build the product right that’s highly automated.
Understand each of the practices focus, outputs and benefits and use them when suits your needs. For example, because is an indicator to be an outside-in workflow, doesn’t mean you can’t go from inside-out. And don’t bias yourself to tools, I’m using BDD tool so doing BDD.
Personally, I keep it simple and use the BDD term when the approach is about the collaboration with all stakeholders (customer, developer, tester, etc) to build the right product and produce living documentation that’s readable by everyone to describe what the system can do. TDD is about designing and building the product right.
Hope this helps.
If you’d like to know more or how we can help you or your teams incorporate these practices then check out our Technical Agility services or get in touch at info@bagile.co.uk