Over the years I have introduced TDD practices to multiple teams, both as an engineer and as a consultant. Often I find that teams have some awareness of TDD process and tools, but have fundamental misunderstandings about the process and its benefits. The initial perception that I generally see is that TDD adds work to the development cycle while adding minimal benefit. In fact, although adopting TDD requires some time investment, the final benefits far outweigh the initial pain points.
In a way, the process of adopting TDD is very similar to committing to a fitness goal:
Imagine a person who wants to participate in an upcoming 5k event. Although they are in good general health, perhaps they are unaccustomed to sustained walking, and so will have to work their way up to the goal. In many ways, this process is similar to adopting TDD:
- Success requires commitment to change
- There is a certain amount of initial investment required
- Often there are pain points during the initial phases but these diminish with time
Goal: I want to walk in an upcoming 5k event so that I can improve my health.
Goal: We want to adopt TDD processes so we can improve our software’s stability and quality.
- Time spent exercising
- Walking shoes, water bottle, etc.
- Designing and implementing test infrastructure
- Initial effort typically involves significant refactoring to enable testing of existing code
- Most TDD tools are open-source, so there is not usually a significant financial outlay to adopt TDD
Initial Pain Points:
- Physical pain
- Lifestyle changes (e.g. dietary changes, workout schedule)
- Learning curve (e.g. new exercises, nutrition)
- Learning curve: Learning new toolchains, design patterns, and workflows
- Workflow changes: Test-driven development, continuous integration, continuous improvement
- Mindset changes: Elevating testability to a primary design consideration, commitment to the workflow
Commitment, Motivation, and Dedication Requirement:
- Must exercise regularly
- Must adhere to strict diet
- If not properly motivated, failure is likely
- Team buy-in is vital; Lack of commitment severely diminishes the process’ value
- Strong leadership and guidance are crucial to ensuring uniform adoption and application of TDD processes across the team
- Institutional inertia (e.g. “Why change now?”, “That sounds like too much work!”) can also pose a problem, particularly on brownfield projects
- If you stop exercising once you’ve got the abs, they will go away
- As health improves, maintenance effort diminishes to a certain point
- Test code carries a similar maintenance burden to production code; As production code matures and is refactored, corresponding changes are required in test code
- Usually in a mature TDD project, test maintenance investment decreases over time to approximately 10% of total coding investment
- After achieving the initial goal, there is ongoing maintenance to retain the benefits
- Starting condition may be far from the desired end state
- Legacy code is often difficult or impossible to test due to hidden dependencies
- Tightly-coupled code is extremely difficult to test in isolation
- Can work around this by adopting TDD for all new code and gradually refactoring the existing code to a more testable state, however this refactoring can be very time-consuming and risky
At this point it should be fairly clear that adopting TDD isn’t a simple or light undertaking. Initially it requires a significant outlay of effort combined with a substantial learning curve, however the effort diminishes as the project matures. In my next blog post, I’ll examine the benefits that TDD can bring to your project.