Why Fail First Approach Like Test-Driven Development (TDD) Is Overlooked?
A couple of days ago, I was watching my friend who just began studying computer science and programming writing a simple Python code.
He was instructed by his mentor to start writing failing test cases first and make them pass subsequently by implementing just that feature.
He continued doing this approach with great enthusiasm until eventually, he implemented all the required use cases with an astonishing 100% test coverage! For him, it was just as easy as wiring the question first and then answering it in the next step.
He never programmed or never knew any other approach to programming. Therefore, it was quite natural for him to do so.
While 100% test coverage is a highly ambitious target in enterprise level software program, in my friend’s academic project, it wasn’t really an unattainable mark.
While I felt happy for him, I thought for a while and wondered why many of the seasoned programmers don’t really get so excited about this approach.
In many instances, we are naively trapped in the below Anti-Pattern
Write Code → Code Successful (visibly) → Refactor → Write Tests based on the implemented code → Written Tests are Passed → Send to code review → Merge code → CI/CD → Push to production
While being in in this anti-pattern, we are losing the real benefits of Test-Driven Developments like Code Quality, Lower Code Maintenance and most importantly, low financial expenses in building and maintaining large scale software products and projects.
But what could be the reason for this mental block?
The first five things came to my mind why many professional programmers fail to embrace the extra ordinary benefits of Test-Driven Development (TDD) are:
1. Natural tendency to avoid failure
It’s a well know human cognitive self-serving bias to claim more responsibility for successes than failures. From an evolutionary perspective, humans are driven by the zeal for success than failures. Any failures in the evolutionary terms would have been catastrophic in the course of human life. Therefore, it’s not a surprise that we tend to avoid failures.
Paradoxical to this human bias, TDD is driven by the zeal to fail first. Consequently, it needs considerable understanding and practice of this idea to make habitual for every line of code we write.
2. Eager to implement the feature first
It’s also natural to us as programmers to be keen to implement the features first. It gives us a sense of accomplishment. We tend to disregard the importance of writing failing test cases first. We think it’s okay to write “few test” cases after we implement the features. After all we are accountable for the test coverage displayed in our static and dynamic code analyzers!
3. Project needs to deliver fast
At least few of the Project Leaders do not realize the importance of TDD. To them, delivering product on time with their own perceived “Quality” is more important. In this context, the term “Quality” can be subjective. The perceived product quality of a programmer can be different from product leaders or sales team. In my opinion, the product Quality should not be subjective rather based on clearly defined objectives. Every product we develop is different in several ways and it would be great if we can define what is the quality for a product with clear terms. One example, though very idealistic, is of having “Zero Bugs”.
TDD is clearly one of the ways to achive this.
4. Limited proficiency in testing frameworks
Another reason many programmers overlook TDD is their lack of expertise in Testing Frameworks and Testing in general. While the basic Unit Testing remains simple and straightforward, the availability of countless testing frameworks, especially for enterprise and cloud native projects, takes time for programmers to learn and adapt. Thus, naturally programmers favor the easier option of implementing feature first under pressure.
5. Lack of Software Craftmanship
Mastering Software Craftmanship takes time, effort and continuous learning. Many individuals and companies drive the quest for Software Craftmanship. Software just written is not enough, we need to aim for perfection to the knowledge we have. Lack of motivation in Software Craftsmanship could make the developers fail to understand the importance of fail-first approach.
The reality, however, is that TDD helps you prevent bugs. TDD make you fail first but not in the last moment. The chances of potential bugs after the product release is considerably lower (surely based on the percentage of test coverage).
The cost of fixing and releasing a bug is exponentially higher than the extra effort in spending time in writing failing test cases first.
So, what really is a suitable pattern for TDD?
While there are several popular patterns in Test Driven Development, my personal favorite is the below pattern.
Like my friend, follow the simple question answer approach while writing code. Take few brakes if you are irritated. Enjoy the journey. You will start enjoying it and eventually become a habit. After all you will be one more step close in perfecting the art of Software Craftmanship while your company deliver quality products to its customers with minimum maintenance costs.