Achieve Instant Feedback with Test Driven Development
Written on
Chapter 1: The Power of Immediate Feedback
Imagine a scenario where every member of your development team can demonstrate that their code worked just thirty seconds ago. You could walk through the office, stopping at each desk, and within half a minute, see everything functioning perfectly. How would this shift your perspective on software development?
The TDD Cycle
When Kent Beck introduced his book on Test Driven Development (TDD), he encapsulated the process with a simple mantra: red-green-refactor. These three terms describe an ongoing cycle that should be executed swiftly, ideally within a minute.
This cycle begins when a programmer writes a test, observes it fail, and then implements just enough code to make it pass. Once the test is successful, refactoring can take place. At this point, the tests are green, indicating that the program is functioning as intended.
The effectiveness of the TDD mantra lies in preventing developers from getting stuck in prolonged coding phases without confirming functionality. It also streamlines the process of implementing changes and ensures team alignment.
The apparent ease of achieving a working codebase in mere seconds through TDD might seem self-evident, yet sometimes the most straightforward concepts are the least recognized. Consider the circle: most can define it, yet drawing two circles to find points at equal distances from two centers is not as intuitive as it sounds. The same principle applies to the implications of the TDD mantra.
Challenges in Implementation
There are situations where strictly adhering to the TDD mantra isn't feasible. For instance, if we are dealing with a large-scale system that has thousands of tests—each taking less than 0.05 seconds to run—the cumulative time to execute all tests can exceed one minute, making the mantra impractical. Should we abandon it altogether?
Absolutely not. We can still leverage the benefits of TDD. One key advantage is its capacity to enhance design and decouple code. By concentrating on the current test suites or the most critical tests, we can maintain rapid iteration.
If we limit our focus to the immediate test suite and do not run all tests with each cycle, it's crucial to periodically execute the entire suite. Ideal moments for this are just before breaks or through a pipeline at every commit. If a test fails, you can easily revert and try again.
On a personal note, I opted for an M1 Max laptop after my previous Intel i7 11th generation took two minutes to run all tests. With the M1 Max, the duration shrank to just fifteen seconds. While I still prefer to avoid waiting even that long, now I receive feedback on one suite in under 0.2 seconds, which feels almost instantaneous. Frequent testing has become a part of my workflow.