Popularised by Kent Beck, TDD is a practice of Extreme programming. During recent years it has become increasingly adopted throughout the software industry. As a sign of this popularity, the first international TDD conference was held on July 10, 2021, as a community effort to bring together TDD practitioners, share ideas, and start a conversation about the future of TDD.
This post will share TDD insights and education from experts and is a summary of what was discussed at the conference. As well as highlighting why TDD is important, and when to use TDD successfully.
The order in which the talks are referenced here is not the same as in the conference. This is intended, as the timeline here tries to combine subjects that are related (but feel free to read the sections as you like).
- Introduction Keynote - Alex Bunardzic
- Take many more, much smaller steps - GeePaw Hill
- Agile pain relief through technical excellence - James Grenning
- Why you might not want to use TDD - Ola Kunysz
- TDD Misconceptions - Olena Borzenko
- Avoiding Common TDD pitfalls - Job Mit
- Writing robust tests with TDD - Mario Cervera
- TDD Manifesto - Daniel Moka
- Python, a language made for TDD - Jan Giacomelli
- TDD on Legacy Systems - Maximiliano Contieri
- TDD all the things - Liz Keough
- Benefits from going beyond “make it work” phase - Fran Climent
- TDD or API-first - Meenakshi Dhanani
Keynote - Alex Bunardzic
Alex started the day by giving a general overview of his career, TDD, and how he personally sees the future of TDD. Importantly, as an organizer of the conference, he left from the beginning the contribution of the conference for further generations of developers to come.
The introduction keynote was right on track for opening this event and leading TDD as a standard. During this talk, Alex gave his insight on how he approaches TDD and its benefits of avoiding debugging time thus increasing productivity, not manually running the app through the UI, logging X times and click around, and avoiding messing around with configuration files.
As a closing note, Ales allowed Gee Paw to start his presentation as he ended, continuing the flow of TDD.
Take many more, much smaller steps - GeePaw Hill
GeePaw started his talk elaborating on the steps that the TDD approach provides, he explains “that if you want to go fast, change code faster, value faster, take many more smaller steps” This reminded me of Uncle's Bob quote, "The only way to go fast is to go well", which supports GeePaws claim in the approach you need to take.
He follows on with the flaws of waterfall, and the pain that development teams suffer following this process (defined in the '80s):
- Decomposed upfront
- Divide the load among teams
- Assemble at the end
- Build forever
Those flaws are continuously mentioned throughout the talk, as he elaborates on why smaller steps help on the wait to shift thinking that the industry has from the past. So the proposal here should be focused on the step size and human behaviour.
Software changes all the time, the terrain changes because of new techniques, new frameworks and most importantly business changes all the time.
GeePaw calls Directed Parallelism the parallel tasks that developers usually do on a daily basis, such as meetings and updating Jira.
Smaller steps have intrinsic benefits, especially if we are talking about systems that involve humans.
if you interrupt me I have to start all over again, this is because you are between two states, between completeness. You can't be interrupted. On the other hand, if you take smaller steps, you can make it as small as it can be, to be able to make room for those interruptions.
I can't steer in the middle of a step, but ifI am finished, I can change direction and go on after that.
It's ok to be wrong, if you are coding, it is fine to take it back. Reset, start over again. Reversibility means you can reverse a step whenever it is needed.
Ability to poke the entire step on our head, understand immediately, another type of juggling. In code is usually the term of, how many small pieces I have in place before deploying.
Humans use rhythms very successfully, periods of attention, periods of release. It has a biomechanical impact on our brains, smaller steps, gives us better rhythm.
The granularity of steps play a vital role for parallelism, it links to In interruptibility for example. Smaller steps enable parallelism to play into the day to day of a developer.
- Hierarchical Command & Control
- Additive Production Reasoning
- Test-Driven Development
- Path-Focused Design
- Mobbing, Pairing, Swarming
Agile pain relief through technical excellence - James Grenning
James started his talk by exploring the technical excellence of software development. Surprisingly, James’s talk started 10 years ago when SCRUM people invited him to talk at a SCRUM meeting about technical excellence. This is interesting as the SCRUM focuses on the management aspect of software development leaving technical excellence as a second thought (Martin Fowler, shared the same opinion in a blog post on his website, on this youtube video, Sandro Mancuso gives his thoughts on this subject as well).
James is the signer of agile manifesto and has his roots on XP, the talk progresses through examples of how software used to be developed, in the waterfall way.
James based his talk on the lack of focus on the technical aspect of software development, for example, he showed a chart with the increasing SCRUM certified people since and started an argument that even after that many certified people, we still are failing from delays and frustration on software projects. For James, SCRUM is focused purely on the management rituals and forgets about the engineering skills.
"People are only doing the easy half of agile, the other half is technical excellence side"
The following picture depicts the agile adoption pain scale presented by James:
Interestingly enough, James starts to base his argument of technical excellence on bugs, which leads to the statement by Edsger Dijkstra:
"If you want more effective developers, you will discover that they should not waste their time debugging".
(this links to Alex’s initial Keynote). James also links TDD as a way to avoid time debugging, iteratively.
More importantly to this mix, James also points out that it is not only TDD that should be the star on the technical excellence side, techniques as refactoring is also important as well as the human aspect of it.
The main take always from James talk is that agile is a triangle that holds:
- Iterative planning
- Respect for people
- Technical excellence
Why you might not want to use TDD? - Ola Kunysz
Often when starting with TDD we want to use it everywhere or on every project, for that Ola brings another point of view: Have you ever thought why you might not use TDD? The title, however, is slightly misleading but the talk does connect the dots.
Ola, started her talk with the foundation of TDD and enumeration three ideas:
- TDD changes your tests
- TDD changes your code ( as it pushes the baby steps approach )
- And finally, it changes the way you think
The first reason you might not want to use TDD: you might find it difficult to start, this simple idea is the idea of the whole technique, but remember simple is not easy.
There is a point that she mentioned that caught my attention around experience, she says "The more experience you have the more difficult it is", to overcome that the suggestion is to watch live coding.
It's hard to follow the process, it is somehow connected to the previous point of experience. Sometimes, experienced developers tend to jump to the final implementation code, skipping the smallest step, refactoring and not following the flow.
Maybe this is the most challenging one and is pointed to people with experience on TDD: levelling up on TDD is not easy. She proposes katas to improve TDD skills. Therefore, she mentions that it is important to get started with the process of TDD and then move to real-life problems, like pair programming and also implement some real requirements.
To sum up
- TDD is a great technique but it is hard to start
- It's hard to follow the process (RED, GREEN, REFACTor)
- It's hard to level up
What you might need to overcome those issues:
- Watch live coding
- Follow the process without judging
- Practice, practice, practice
TDD Misconceptions - Olena Borzenko
During TDD Misconceptions, Olena Borzenko explored the way of thinking on TDD for real-life projects, and how to use TDD in practice. The misconceptions that Olena described during this session are highly relatable, and often raised by developers that don't have much experience following the practice or even haven't started to practice yet.
Misconception 1: TDD is when you write all the tests before the business logic
- Requirements were changing with the same speed as customer mood
- Confusion on an inexperienced team
- Lack of understanding
Misconception 2: 100% code coverage
- Tests were written just for coverage purposes
- Too many mocks
- Critical defects were still there
Misconception 3: time-consuming
- TDD is time-consuming
- Red, Green and Always refactor
- Simple code needs no test
Avoiding common TDD pitfalls - Job Mit
Avoiding common TDD pitfalls was a hands-on session by Job Mit. The session went through the implementation of search functionality using kotlin, before getting the hands dirty, he also gave some explanation on the different styles of TDD, named Inside-Out (Chicago) and Mockist (London), the following list depicts the highlights:
TDD Chicago: classist (Inside-Out)
- Inside out (how you design the software)
- Design in the green (fake until you make it)
TDD London: mockist
- Outside and go inside
- Design in the red
- It uses mocks
Jovi elaborates on how to get started with TDD with the search functionality. For beginners, he recommends scratching out examples over paper and trying a few test cases. On the other hand, for more experienced developers, he recommends the Z.O.M.B.I.E.S approach
Z - Zero
O - One
M - Many (More complex)
B -Boundary behaviours
I - Interface definitions
E - Exceptional behaviour
S - Simple scenarios, simple solutions
Ending the session, Jovi states that TDD should be easy to understand. However, you need practice, knowledge of architecture, and be able to understand how systems interact with one another.
The resource shared at the end of the talk was a video Sandro Mancuso recorded with Uncle Bob comparing the two schools of thought on TDD.
Writing robust tests with TDD - Mario Cervera
Starting by reviewing the title, Mario shares common ground on how TDD can help us avoid writing fragile tests, as well as the notion about the unit and coupling during his presentation.
Definition: fragile tests are tests that break when the behaviour does not change.
Problem: tests should aid refactoring, not block it
Cause: high coupling
On the subject of coupling, Mario references a talk that Sandro Mancuso gave at DevTernity on the relationship between a unit size. The explanation goes on the line between aggregation and composition, whereas on the aggregate classes you might want to test the class in isolation and on composition the group of classes is what matters. This way of thinking as Mario explains goes hand in hand with outside in TDD.
Code centric view
- Start writing the test
- Start from the outside
- Mock dependencies - mockist approach
- Mocks are used to design the interface, how it should look like
- The structure of the test and the source are equivalent, forced to update the test when refactoring (one class test to one source code file)
- It leads to fragile tests
Behaviour centric view
"Adding a new class is not the trigger for writing a new test. The trigger is implementing a new behaviour" - Ian Copper, 2017, DevTernity
- Thinning about behaviour, units of behaviour
- Given, when, then (BDD, TDD can be considered the same as BDD)
- High coupling leads to fragile tests
- Classic TDD focus on behaviour
- Refactoring is the key step in TDD
TDD Manifesto - Daniel Moka
Daniel's talk on TDD Manifestos was one I was personally looking forward to the most, given that the software industry takes manifestos as a starting point to build on top of. Having a TDD manifesto gives the practice even more power to keep evolving and push the industry forward.
The motivation behind the TDD manifesto is based on the 20th agile manifesto anniversary, misunderstanding in the space and the lack of such a manifesto for the industry.
Values of TDD
- Baby steps instead of large-scale changes
- Continuous refactoring
- Automated tests
- Executable documentation
- Minimalist code
What is NOT TDD
- A testing strategy
- A design principle
- Imperative shell
- For performance and UX tests
- Solving human problems
On those points, I give a special highlight to the ‘continuous refactoring’ as Sandro Mancuso also challenges this idea of using TDD as a design principle, you can watch his talk here.
The getting started section in the TDD Manifesto is a section that goes through the basics of TDD for newcomers. For example, the section reviews why you might want to use the test first. This section is elaborate, allowing a vast amount of insight for newcomers that might not have any experience with TDD and gives them a path to start.
Besides that, it also suggests katas to start with TDD, we at Codurance have our own kata catalogue to keep our TDD skills sharp, it's called katalyst.
A clean test
Clean can be subjective. However, the clean test is defined by a set of characteristics that it should comply with, for example:
- Descriptive test name
- Meaningful names
- Structured with Arrange-Act-Assert (AAA) pattern
- Follows the F.I.R.S.T principle
- Uses meaningful data
- Hide irrelevant data for the test
This section is all about exercising your TDD skills using katas, the TDD manifesto suggests a few katas to do that, and as previously mentioned, Codurance follows the same strategy at katalyst - which also provides great education for TDD skillset.
Python, a language made for TDD - Jan Giacomelli
Jan, started his talk on a theoretical basis, elaborating on the differences between the test library that comes with python and the library pytests. This session was hands-on and the TDD flow is followed using the libraries described, for a detailed approach on how Jan follows the Red, Green, Blue, Flow - watch his talk here.
Python comes with a standard library, it is a xunit implementation in python and it also comes with a mock library already.
- Less boilerplate code
- Uses built-in assert statements
- Set up, tear down and fixture system
- Functional approach
- Plugins available
Python and ML
Finishing up the talk, Jan elaborates on how TDD (red, green, refactor) is similar to the scientific method (hypothesis, validate hypothesis, theoretical hypothesis), on that basis he points towards usage of python tests to validate machine learning models.
At Codurance Javier Martinez wrote about testing with Python, more specifically, on mocking. The blog post is a walkthrough of mocking with pytest, it has a video companion to go over the content. It is insightful as follow up reading on this topic.
TDD on Legacy Systems - Maximiliano Contieri
From my previous experience, applying TDD to legacy systems is challenging, to say the least. Compared to green field projects TDD should be used from the first day, unfortunately, on legacy systems, usually it's not the case. Legacy systems are known for spaghetti code and lack of good practices around.
Given the importance of legacy systems, it's usually good to think about modernizing them, as such, applying TDD could be the first step towards the end goal. Codurance has a section on this subject as well, on our official website you will find videos, podcasts and posts about this subject.
Maximiliano draws a line between the katas to train the TDD skills and the legacy systems during his talk, and on the same lines he enumeration a few bullets on TDD myths:
- TDD does not guarantee good design
- TDD does not guarantee good design
- We cannot use TDD on coupled systems
- Code must be clean all the time
- Software development is an individual process
- Requirements are frozen
- During TDD only programmers write tests
- We should test private methods
TDD all the things - Liz Keough
Liz introduced her talk on a BDD basis, which created a common ground for her to follow up on TDD. The main takeaway for me from this session is that Liz makes a statement that she will use BDD instead of TDD. Mario in his talk also talks about behaviour during TDD, in other words, confirming that TDD is also about the behaviour.
Liz explains that TDD a person is about applying the TDD flow, "People are like legacy systems, they already have an existing behaviour."
This talk by Liz depicts how TDD can be used as an analogy to other subjects besides coding.
Benefits from going beyond “make it work” phase - Fran Climent
Fran Climent touches upon a specific topic regarding embedded systems that are difficult to accomplish: TDD on embedded systems. As you might already know, embedded systems are dependent on platform, code and compilers make it even harder to test drive a solution.
Fran gives a walk-through on a journey to improve this scenario on a test-driven embed application. I share some opinions on that, as I had to work on arduino projects, which were not common to test drive any of the code built there.
Even Though the talk was focused on embed systems, Fran finishes the talk with a few insights that are related to any agile project:
- Debugging is a shame: when debugging we are adding zero value to our organization
- Measure your lead time to know your bottlenecks
- Test later is a testing technique focused on external quality only
Speed as a workplace habit - Ragunath Athjawahar
Ragunath started his talk by elaborating on the feedback loop that TDD offers, and the positive impact that it has on any kind of workflow. To depict that idea, he uses the analogy from an IDE (Integrated Development Environment), going all the way to solving problems. The talk is structured around the following topics:
- Learning shortcuts 1 and 2 - How we as developers learn shortcuts and the feedback value that we get from the IDE
- Writing a blog post - The same pattern applies here, the positive feedback on writing a blog post on an editor
- Working with Graphical User Interface (GUI) - On this topic, Ragunath changed the focus saying how the GUI is not efficient and how their feedback flow works as a not efficient compared to an editor
- Exploratory problem solving - Test drive even when the problem is not related to tech, for example, a bank statement
As a closing note Ragunath also cites Uncle Bob on the same quote that GeePaw Hill uses in his talk:
The feedback cycle needs to be excellent, as such the classification is as follows:
- Fail fast
- Grab your attention
- Suggest corrective action
- Command-Line Interfaces enable exploratory problem solving and bug discovery
TDD or API-first - Meenakshi Dhanani
Meenaskshi is a developer advocate of postman and she talked about the difference between TDD and API contract first. A comparison to understand the pros and cons of each approach. The first half of the talk explores the Code by contract, followed by an overview of the TDD approach.
The next step is divided into showing how to use postman to build an API first based on the OpenAPI definition, postman can use this pattern to build a mock api server.
To sum it up, Meenaskshi shows the following comparison table:
In the end, Meenaskshi points out that both approaches should be used together to achieve both benefits from TDD and API-first.
Why I Love TDD And Why I'm Looking For Ways To Go Beyond TDD
The conference closes with Alex test driving a calculator kata, the big surprise comes when he is almost finishing his talk and introduces mutation testing.
From his talk, mutation testing seems to be one of the aspects of automated testing for the present and future.
The practice of writing tests before production code has been around for many years now and the interest in it has increased over the years. As an example, the TDD conf gathered professionals across different fields in the industry to talk about TDD all day long. Talks that cover a side set of themes related to TDD, to name a few: miss conceptions on TDD, testing machine learning models with python, approaching legacy systems and writing robust tests.
Initiatives like that push the industry forward in the standardization of the quality in the work that software developers do, and on the flip side, it also exposes the need for the industry to keep moving forward and improving. TDD was popularized by Kent Beck and we as an industry keep this moving alive discovering new ways of building on top of that. Mutation testing is an example of that.
For now, we know that TDD is a stamp that guides developers on building quality software, and probably it will be for years to come. Therefore, imagine having artificial intelligence also playing a role in this game, spotting defects based on cases that the test suite didn't cover, or for example, having a companion helping out writing more effective tests.
In conclusion, I am excited about the future of testing in software development and you should too, but until then, we will keep sharing what we find interesting in the TDD world.