Mastering Continuous Delivery: A Deep Dive into Test-Driven Development and Testing in Production
In the realm of software development, achieving seamless continuous delivery is a challenging yet rewarding endeavor. In their insightful talk at QCon London, Ola Hast and Asgaut Mjølne Söderbom shed light on their unique approach to continuous delivery, emphasizing the power of test-driven development (TDD) and testing in production. They shared their journey, highlighting the benefits of focusing on unit and integration tests over end-to-end tests, and the importance of pairing programming and continuous integration for enhanced code quality and team resilience.
Embracing TDD and Pair Programming
Hast and Mjølne Söderbom advocate for a strong reliance on unit and integration tests, trusting them individually and collectively. They have consciously moved away from end-to-end tests, prioritizing a modular and domain-driven design approach. This shift is achieved through good separation of concerns, modularity, abstraction, low coupling, and high cohesion, which are fundamental principles of TDD and pair programming.
Testing in Production: The Ultimate Feedback Loop
Recognizing the limitations of test environments, the team has embraced testing in production. Mjølne Söderbom explained that production provides the most authentic and high-quality feedback, free from the constraints of long supply chains and flawed test data. By deploying small changes and features behind toggles, they minimize risks and ensure that any issues are quickly identified, fixed, and rolled back or forward.
The Power of Pair Programming and Continuous Integration
Pair programming and continuous integration work hand in hand, according to Hast and Mjølne Söderbom. Frequent pushes to the main branch, multiple times a day, can be challenging in isolation, leading to delays, large pull requests, and merge conflicts. However, pairing enables instant code reviews, seamless refactoring, reduced bugs, and heightened team resilience. This collaborative approach is a cornerstone of their development process.
Minimizing Tests, Maximizing Real-World Feedback
Hast revealed that they have significantly reduced the number of tests, focusing primarily on happy path tests and additional tests for special error scenarios. They believe that what cannot be tested with unit tests is best tested in production. This philosophy stems from the understanding that test environments are always approximations of reality, often struggling with long supply chains and poor data quality. The team's priority is to obtain the most valuable feedback from production, which has become a natural consequence of their development practices.
The Importance of Feedback Loops
Mjølne Söderbom emphasized the critical role of feedback loops in guiding the development process. Feedback enables the team to navigate, make decisions, and adapt when necessary. They prioritize fast feedback loops at all stages of development, with TDD playing a pivotal role in providing early and rapid feedback.
TDD: A Design Tool, Not Just a Testing Method
Hast challenged the common perception of TDD as solely a testing tool. He argued that TDD is fundamentally a design tool, and the presence of proper tests that facilitate a smooth development flow is a valuable side effect. This perspective highlights the importance of design considerations in TDD, where the code 'talks' to the developers, driving the design process.
In conclusion, Hast and Mjølne Söderbom's approach to continuous delivery, centered around TDD and testing in production, showcases a thoughtful and strategic methodology. By embracing pair programming, minimizing tests, and prioritizing real-world feedback, they have achieved a high level of code quality and team efficiency. Their journey serves as an inspiring example for developers seeking to master continuous delivery practices.