⏩ Introduction
Software development is a field that is constantly evolving, and with it, the practices and methodologies used to build software applications. Test-driven development (TDD) is a practice that has been gaining popularity in recent years. However, some are still skeptical about its effectiveness.
It's not uncommon to come across developers who argue that TDD is a waste of time, that it slows down the development process, and that it's just another buzzword that doesn't actually deliver on its promises. These arguments are typically based on misconceptions and misunderstandings about what TDD is and how it works.
That's where objective data comes in.
By using data to back up the claims about the effectiveness of TDD, we can fight the skepticism and misunderstandings that exist around this practice. Data can help us to understand the value of TDD, and to make informed decisions about whether or not to adopt it as part of our development process.
In this article, I will delve into the objective evidence that proves TDD is effective. By doing so, I hope to help those who are on the fence about TDD to understand the value of this practice and give it a try. 🧐💡📈
📈 A data-driven TDD exploration
Test-Driven Development is one of the technical practices of eXtreme Programming, whose invention is usually attributed to Kent Beck, one of the first “extreme programmers”. TDD is one of the most discussed topics about Agile practices and technical excellence, yet is still one of the less used and a lot of people still think it is not a good practice, for multiple reasons.
Many software engineers express this feeling: they see Agile as a "religion" or "cult" supported by people that look more like fans than developers supporting good practices. I disagree, of course, but we have to admit that sometimes some of us behave like fanatics.
When a developer builds the habit of writing tests, he/she begins to see any developer who does not create tests as lazy or an idiot. We stop asking ourselves why we test and begin asking others, such as "Don't you want your code to work?" as if that's going to help.
Spoiler: it’s not helpful at all - and if we really want to make a difference and spread the Agile practices and methodologies in order to improve our community, we have to improve the way we communicate them.
This situation is most often expressed when talking about TDD.
TDD is not a universally accepted practice, most teams don’t do it. You may think it’s because they’re lazy or stupid, but it’s not - it’s mainly because they don’t believe it’s helpful. I’ve seen great developers, totally into writing tests (after), not applying practices such as TDD or TBD (Trunk-Based Development).
At the time, I wasn’t so skilled to challenge them on those topics, and once I started to master TDD, TBD and all that kinds of practices, I started asking myself: why such great developers don’t apply them?
At first, I was approaching this question with the same fanatism I said before, and thought “Well, they weren’t that good, overall”. False: they were great developers.
After some weeks, I tried to face this with a more critical and objective approach to understand if I was missing something or if they were missing something, or if it was just a trade-off, as always.
📴 The trade-offs with TDD
I want to make a clear statement before starting this analysis: TDD doesn’t take long and doesn’t have any kind of trade-off related to productivity, time to work on a task, etc.
The fact that a developer might be slower at first with TDD is not a trade-off, it’s just how learning works - and, by the way, you shouldn’t learn while working on a real feature, you should learn in katas and exercises projects until you are confident enough to make a real software feature.
TDD actually has only positive effects, once you master it. So, what are the trade-offs I’m mentioning in the header of this section?
All the trade-offs in TDD are about the developer itself: learning TDD means being able to accept that the way we worked up until now must be totally changed. You must be open-minded, ready to accept that there is a better way to achieve the result avoiding bugs, defects, extra effort and having a final code that overall is easier to maintain, thanks to the test suite.
The truth is simple: TDD is hard, and not all developers care about their job enough to study, learn and improve in something so hard.
🔦 Data and research supporting TDD
TDD is one of that strategies that are simple, not easy.
The TDD cycle is easy to understand (red, green, refactor), but very very hard to implement correctly. The first attempts are always frustrating because it’s a counterintuitive practice.
So, why focus on learning something that hard? Is it really worth it?
I didn’t simply want to answer this question with my own head, so I searched the internet for some research and any other kind of objective data I could find in order to sustain that mastering TDD is really worth it!
And guess what? I found them! A lot, actually! More than I could expect. You will find a full list of all the research and blog posts in the “Go Deeper 🔎“ section - here are a couple of examples.
-
In Test-Driven Development as a Defect-Reduction Practice, the study reach this conclusion
In this case study, we found that the code developed using a test-driven development practice showed, during functional verification and regression tests, approximately 40% fewer defects than a baseline prior product developed in a more traditional fashion. The productivity of the team was not impacted by the additional focus on producing automated test cases.
Consider that this result was reached without fixing the defects: fixing them would have led to even more improved productivity.
-
In How to Measure the ROI of BDD and TDD article, we see an attempt to measure the impact of TDD and BDD - and two main metrics were found:
-
TDD teams had 40% to 90% fewer defects.
-
TDD teams spent 15 to 33% more time writing code.
TDD/BDD was able to obtain a better product, with fewer defects and less time invested.
-
-
In Measuring TDD Effectiveness article, more benefits were documented thanks to some metrics, and the conclusions are:
-
TDD results in better-quality code
-
TDD really needs management buy-in
-
TDD is a long-term win
-
Searching online you can find a very large amount of that kind of research and objective data and metrics collected to verify if there is some kind of “scientific evidence” of the benefits promised from TDD.
What does this mean?
The purpose of collecting all this data is simple: helping the sceptics to understand how much valuable is TDD in developing software.
There are typically 3 reasons why TDD is feared/not like:
-
Don’t believe in TDD effectiveness ➡️ This should be totally removed by all this objective data
-
Thinking is not ok for our project ➡️ Again, all this evidence from different contexts and projects should help - it is proven working in a lot of different places and contexts, do you really think you work on such a special project?
-
Thinking TDD slow down productivity ➡️ Productivity is one of the key metrics in most research, so data helps again here - a common misconception to remove is that you should learn TDD first, then start using it in a real project.
As I mentioned before, in the end, there is only one real reason why TDD is not liked and most developers fear this practice: TDD is very hard.
So, here comes the question: which kind of professional developer do you want to be?
Don’t get me wrong: work is work, and is not mandatory that everyone has a high level of ambition and love in what they do so much to approach it as a continuous learning journey. If you are not that ambitious, that’s ok.
What it’s hard to accept for me is that a lot of people say to be that much ambitious, say they want to improve every day, complain about how much they struggle to keep the quality high in their codebases, typically giving the responsibility to managers, etc. Then, they refuse to learn advanced techniques like TDD, but also advanced refactoring practices, CI/Trunk-Based Development, etc.
Those are the practices that are proven to work in software development history, so trust them. Your life as a Software Developer will never be the same. You will achieve results you could never imagine.
Until next time, happy coding! 🤓👩💻👨💻
Dan’s take 🙋🏻♂️
TDD is by far my preferred software development technique, for multiple reasons: when I first read the original book from Kent Beck, I was amazed - and I decided that I wanted to master it. So I started practising until doing TDD became normal for me, in my daily work. It took a week to feel confident enough to try it in a task, and months to start feeling like I was mastering it. I’m probably still not mastering it thou, after 3 years of everyday TDD.
I understand the fear: TDD actually IS very hard.
It has a lot of shades of grey, multiple positive effects, and multiple aspects to be understood - is not only about software development itself, is about problem exploration, solution crafting, and moving in baby steps.
For me, it was that much enlightening that I fell in love with everything, and decided to study every aspect in deep. It doesn’t have to be this way for everyone.
I would split TDD into 3 main pieces, and my tip would be to focus on one of them at a time in order to maximize the learning of every aspect, starting from the one that you care about the most.
The first one is Software Development.
This is the part related to the concept of “test first”, which is only one piece of TDD.
Learn about the TDD Cycle, and the 3 Laws of TDD, and start writing tests before implementing the code and enforcing the use of the refactoring step to keep the design of your code in shape. This will lead you to a code with better quality, readability, and maintainability.
The second aspect is moving in baby steps.
Learning to write tests first is not the only point of TDD: you should also ensure to move in the smallest steps possible while doing it. What does it mean?
It means learning to apply tactical GIT concepts to the TDD cycle steps, and learning to respect the timing of the TDD cycle in a natural way: every step should take seconds, not minutes, and you should commit at every step and every refactoring advancement.
This is very powerful and will lead you to an incredible increase in productivity: learning this approach made me able to make a small advancement in a feature in minutes, which makes it super easier to handle interrupts and unplanned work in general.
The third piece is problem exploration.
TDD is a great coding technique, but it’s not only about coding. TDD is also a problem-solving technique embedded during the coding practice.
TDD is always great, but it’s definitely far better when you are facing a problem that you don’t know how to solve. Starting from the tests will lead you to think about how you will use the code first, then find an implementation one small step at a time.
Once you learn to master the TDD cycle and work in baby steps, you will realize that you are able to solve a problem starting to code without thinking too much about it before - TDD will lead you to solution implementation.
In general, to learn such hard practices, you have to master learning too.
Embrace the Continuous Improvement approach: make a habit to do Katas for learning things in a safe place. Make a habit to read books, study, take online courses, read blog articles, and listen to podcasts.
Participate in the community: go to conferences, try to give a talk, contribute to OS projects, and join online communities.
You can also create an internal community in your company: ask for a half-day per week for learning and use it for shared learning sessions like book clubs, small talks and meetups, discussions, etc.
Improving yourself is your responsibility, not the company’s. If you want to achieve technical excellence, you have to invest your own time in it!
As an XP advocate, I embrace continuous improvement as a prominent part of the job. As an ambitious developer, I want to achieve technical excellence - not only for personal satisfaction but also because it leads businesses to success.
Learning TDD, together with other practices and methodologies like CI/Trunk-Based, XP, etc, will make you a top-notch Software developer and boost your career in an amazing way.
Go Deeper 🔎
📚 Books
-
Test-Driven Development: An Empirical Evaluation of Agile Practice - this book includes the results of three different experiments, including concrete examples of how to conduct statistical analysis, using as evaluation indicators the number of acceptance tests passed (overall and per hour) and design complexity metrics.
-
Test Driven Development: By Example - the original book from Kent Beck that explains TDD, with examples, and also explain some pitfalls for experts practitioners
-
Learning Test-Driven Development - Author Saleem Siddiqui shows you how to tackle domain complexity using a unit test-driven approach. TDD partitions requirements into small, implementable features, enabling you to solve problems irrespective of the languages and frameworks you use.
-
Growing Object-Oriented Software, Guided by Tests - Implementing TDD effectively: creating cleaner, more expressive, more sustainable code using tests.
📩 Newsletter issues
-
Everything I know about introducing TDD in an org [The Engineering Organisation by svs]
-
Introduction to Predictive TDD [Make Your Code More Testable by Ted M. Young]
-
Use Test-driven Development to Retain Modularity [Crafting Tech Teams by Denis Čahuk]
📄 Blog posts
🎙️ Podcast episodes
-
TDD for today [Thoughtworks Technology podcast]
-
Unit Testing With Test Driven Development [Complete Developer podcast]
-
TDD with Ian Cooper [The Unhandled Exception podcast]
👨🏻🏫 Online courses
-
Test-driven Development: CodeMash [Pluralsight]
-
TestDriven.io [a platform dedicated to TDD courses]
-
TDD micro-learning - Our micro-learning courses catalog offers, among the others, a path dedicated to TDD: learn the core concepts at your own pace in an interactive learning experience
🕵️♀️ Others
➡️ How effective is Test-Driven Development - a research written by the University of Oulu, Carnegie Mellon University and Fraunhofer Center for Experimental Software Engineering