Test-driven development: The key for reducing development costs
In the realm of software development, Test-driven development (TDD) has gained significant traction over the years as a well-regarded methodology. Therefore, in the article below we’ll delve into its origins, objectives, correlation with testing as a whole, and how it can help save development time and costs.
What is test-driven development?
Test-driven development (TDD) is a development practice that was introduced in the late 1990s by Kent Beck. It is part of the Agile methodology known as Extreme Programming. Simply put, it’s a process where the developer binds a given functional requirement to an automated test, and only then proceeds with the actual implementation to satisfy said requirement. Subsequently, the process gets repeated until all such test cases are covered. Three laws[1] ensure the effectiveness of Test-driven development, which are as follows:
- First Law: No production code is written until there is a failing unit test.
- Second Law: Add a unit test that will fail.
- Third Law: No extra production code is written than the one sufficient to pass the currently failing test.
Test-driven development leaves more time for analyzing the design, the requirements, and how the given feature is going to be used by the client. Then the work is separated into small incremental steps, allowing developers to stay focused on one problem at a time. As a result, this usually leads to a more modularized and flexible code base.
When to use test-driven development?
This development technique might promise great results, but it’s not the silver bullet that will help all software projects. Some products are relatively small and need to be delivered quickly. Also, they might not require to be maintained or extended with new functionalities in the future. Such products will be unlikely to benefit from this technique.
Still, using Test-driven development is the obvious answer in the case of:
- Complex software systems
- Highly reliable applications
- Products with changing requirements
A more detailed answer can come from a study by Lehman and Belad[2] on how operating systems are built. The total number of modules in such systems increases linearly with each release. Conversely, the total number of defects per module increases exponentially. All subsequent fixes introduced by the developers tend to disrupt the structure and destabilize the system. As a result, less and less effort is spent on fixing the original problem, but more and more on fixing flaws introduced by earlier fixes. The conclusion of the study is best captured by the infamous mathematician Blaise Pascal, who stated: “Things are always at their best in the beginning”.
Therefore, when we work on long-term software development projects and have complex business logic, Test-driven development can have a crucial impact on the success of the project.
Test-driven development: Accedia success story
For the past few years, I have been working on a customer engagement SaaS solution in the property industry. We are building a comprehensive omnichannel platform for efficient tenant management, which empowers employees with a robust knowledge bank, enabling swift and accurate responses to customer queries. Additionally, the platform offers a comprehensive customer dashboard housing crucial tenant information, such as contracts, payments, and past interactions up to a specified point in time.
Working on a project from the property industry, you will face constantly changing business requirements and a lot of custom-tailored solutions. Therefore, the product has a modular design, utilizing a few levels of abstraction to allow the delivery of an almost unique solution per individual end user. Given those prerequisites, the natural choice of development practice was Test-driven development.
Why test-driven development is the most useful Agile technique for product development?
There is no question that over the past 20 years, the Agile methodologies established themselves as the industry standard for how software should be developed.
Agile methodologies are promising client satisfaction through the continuous delivery of value-adding software, while Test-driven development creates a short test-implement feedback loop that promotes fast iteration. The consequent synergy between the two concepts allows developers to find optimal solutions promptly. For instance, when I had to implement a custom Authorization module in a project using GraphQL with Microsoft .NET, I had no doubt that I needed to use Test-driven development. The approach allowed me to think about the different use cases in advance and to deliver a comprehensive solution from the very first version. Later, when our team needed to add extra functionality, the tests helped me to verify that I was not introducing any unwanted behavior.
In addition, dealing with unexpected requirement changes – often deep into the development process – is a concept native to most Agile frameworks. Fortunately, Test-driven development creates a large suite of tests that can guard the whole system against code changes and untended side effects.
Simplicity can also be regarded as one of the key values of the Agile methodology. Each step of a major process is broken down into smaller, achievable goals for team members to accomplish. Test-driven development follows this principle by promoting the writing of loosely coupled modular and easy-to-test code.
Benefits of using test-driven development
Lower costs
Several studies support the thesis that software teams that use Test-driven development create fewer bugs. For example, a survey conducted by IEEE[3] states that the reduction of bugs compared to teams that don’t use this technique can be between 40% and 80%. The results from case studies[4] conducted by development teams at Microsoft and IBM showed a decrease in the number of defects between 40% and 90%, respectively. The takeaway would be that when we use Test-driven development, we would spend less time on application maintenance.
On this note, a study from the early 1970s by Betty Campbell, a researcher at MIT's Laboratory for Nuclear Science, showed that the maintenance of an application can take 40% or more of the cost of actual development[5]. And the number goes up with the number of people using the application. On top of that, when a bug is fixed, there is a 20% to 50% chance of introducing another one. This creates a vicious cycle of constantly creating and fixing problems, which can be mitigated with the use of Test-driven development.
Moreover, by writing tests first, there is a better chance to find problems with the underlying requirements, which then leads to fewer bugs introduced to production. Naturally, this does come at the price of spending extra time on writing an extensive test suite, though let’s take a look at the following graphic[6]:
The later we find out about a given bug the more damage will be done to the product. And it will cost way more to be fixed.
Shorter delivery time
The truth is that developers need to put in extra effort when using Test-driven development. Therefore, managers estimate that using the technique would lead to a 15% to 35% longer time-to-market [7].
Actually, in real life, it happens that Test-driven development projects finish 30% faster[8] on average compared to others not using this development technique. The difference is due to the fact that bugs will creep out sooner or later. We already know that these could be quite expensive to fix, so the fewer bugs the better.
The psychological side of fixing bugs should be considered as well, as they tend to eat up the developers' time with unnecessary distractions. Fewer production bugs will result in fewer interruptions in the context of feature development. Usually, bugs have high priority. Therefore, developers are pulled out of their work and dumped into the context of the bug. And only once finished with the fix do they need to reabsorb the task they had put aside. This might seem harmless, but each context switch can take up to 20 minutes, time that otherwise can be put into features development. To make things worse, a study conducted by Microsoft Research showed that interrupted tasks take about twice as long to complete and can contain twice as many errors as uninterrupted ones. When using Test-driven development, software engineers can stay more focused on feature development and complete more of them.
For example, a while ago I was part of a team where testing wasn’t prioritized. As a result, most of my time was occupied with bug fixing, which was quite distracting and emotionally frustrating. Once I moved to a team promoting Test-driven development, I was able to spend my time predominantly on feature development. And what’s most important, the clients using the software built with Test-driven development were much happier and more satisfied with the quality of the work.
It’s important to emphasize that Test-driven development can increase the amount of time it takes to implement a feature. However, the overall time spent balances out over the product’s release cycle because of increased product maintainability.
Better product quality
Testing is the most popular quality-improvement activity in modern software development. Using the Test-driven development laws from above and testing for all relevant requirements will ensure that they have been implemented correctly. This leads to cleaner, more modular, and more maintainable code.
The General Principle of software quality is that improving it reduces development costs. Test-driven development brings with it enough test coverage to serve as a precaution to prevent unintentionally changing functionalities. So, changing and extending any product is much easier and faster.
I found the technique extremely useful when I had to implement the Apollo Federation subgraph specification in one of our Microsoft .NET projects. By translating the specifications into unit tests, I was able to build a solution that has now been used for over 2 years, by 3 different teams, and with zero defects so far.
Summary
Test-driven development can be applied in various domains and significantly reduce the defects of the developed product without allowing any productivity reduction. The best option would be to start using the technique from the start. It’s best done incrementally and continuously. As Capers Jones[9] noted:
Software projects with the lowest levels of defects had the shortest development schedules and the highest development productivity... software defect removal is actually the most expensive and time-consuming form of work for software.
There is no question that a technique like Test-driven development should be considered and used on most occasions to help you achieve quicker time-to-market and better success for your project.
Learn more about Accedia’s software development services and let us know if you have any questions!
Sources:
[1] Robert C. Martin, “Clean Code: A Handbook of Agile Software Craftsmanship”, 2008, Pearson
[2] Lehman, M., and L. Belady, "Programming system dynamics" given at the ACM SIGOPS Third Symposium on Operating System Principles, October 1971
[3] IEEE Software Guest Editors' Introduction: TDD-The Art of Fearless Programming, May/June 2007 by Ron Jeffries and Grigori Melnik
[4] Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat, Laurie Williams. Realizing quality improvement through test driven development: results and experiences of four industrial teams. Kluwer Academic Publishers, 2008
[5] Fred Brooks, The Mythical Man-Month: Essays on Software Engineering. Addison-Wesley 1975.
[6] Steve McConnel, Code Complete: A Practical handbook of Software Construction, 2004, Microsoft Press
[7] Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat, Laurie Williams. Realizing quality improvement through test driven development: results and experiences of four industrial teams. Kluwer Academic Publishers, 2008
[8] IEEE Software Guest Editors' Introduction: TDD-The Art of Fearless Programming, May/June 2007 by Ron Jeffries and Grigori Melnik
[9] Software Assessments, Benchmarks and Best Practices, Capers Jones, 2000, Addison-Wesley Professional