This series are heavily inspired by GeePawHill’s takes on TDD
What’s TDD
Test-Driven Development (TDD for short) is a software development approach in which tests are written for a piece of code before this code is written. The goal of TDD is to catch bugs and ensure that the code works as intended from the start.
One way to think about TDD is to imagine a carpenter building a table. Before he even starts any cut, they create a blueprint outlining the table’s dimensions and specifications. Using this blueprint to guide the construction process ensures that the final product meets their expectations. Likewise, TDD involves creating a “blueprint” in the form of automated tests that outline the desired behavior of a piece of code. The tests serve as a guide for writing the code, ensuring that the code meets the desired specifications.
On the reasons to do TDD
Shipping value faster
It enables shipping value more quickly by providing confidence (“code just what you need”), coherence, rhythm, documentation, intention (related to the Indirection concept), and collaboration while gradually requiring less effort.
Constantly designing
It might be impossible to write a single test if we don’t know what to do. So we constantly are sketching over a whiteboard to devise what is intended to be delivered. These sketches evolve from inception to development and refactoring as long as we work on the feature iteratively.
Not about a showcase
Do we test to prove our entire application works? No. We do tests to guarantee that all the parts we deliver do precisely as we intended them to do.
Additionally, we only test what we mean to test; we avoid large combinatorics since they are too expensive and fragile.
On the key aspects of doing TDD
Mirroring
From the TDD standpoint, it’s building an app in a textual codebase to produce both a Shipping App and a Making App, each serving a specific outcome: The Shipping App is built to enable their users to domain things they can do (i.e., business domain), whereas the Making App is made from a superset of the building foundation of the Shipping App plus other artifacts to enable developers to take its parts, isolate, stress, and conduct them to behave as they intend to.
We are not that interested in what the Shipping App does at this stage. We want to take advantage of the Making App because it will allow us to put the Shipping App under the microscope and tell everything about it.
Alternation
During this stage, the developer bounces back and forth between Shipping and Making App. As new interesting parts are integrated into the Shipping App, the Making App adds their counterpart in the form of test sets in an Arrange-Act-Assert fashion (i.e., set the Shipping App into a known state, performing specific actions, and checking the responses).
Isolation
The Shipping App is built according to a Dependency Graph Tree (i.e., parts of the App depend on other features of the App). The Making App actively seeks to isolate each component from its Dependency Graph. It’s like thinking about parts of the Shipping App as if they were “Black Boxes”, and they work perfectly just by themselves.
Isolation is one of the most critical activities of the Making App and one of the most challenging concepts to grasp for TDD newcomers. Unfortunately, failing to learn this concept harms the adoption of TDD.
Isolation significantly impacts the Making App’s speed and usefulness, making it so informatively precise.
How much isolation should be done? There is no recipe to tell this. We need to have a clear understanding and judge as best we can. That’s why mastering TDD does take time.
The Isolation concept is fundamental for us since it defines the conceptual base of our TDD approach (which will be discussed in the upcoming articles of this series).
Iteration
TDD has to do with an intrinsic iterative nature of “testing a bit, code a bit, repeat”, making it an evolutionary activity. A test suite doesn’t change over time by adding more tests but by changing the tests themselves.
Indirection
TDD is not a bulletproof activity: It does not guarantee the Shipping App does what the final user wants or needs; it only proves that it does what the developer thought it would do.
Building a Shipping App is more about putting several pieces together in the right way to do the right thing. If we don’t deliver shipping parts that do what we think they do, we can’t put them together to work as desired.
What’s next
Test-Driven Development (TDD) is a proven method for building high-quality software. By writing tests before code, developers can catch bugs early and ensure that their code meets the desired specifications. With its focus on iterative development and isolated components, TDD helps teams ship value faster and with confidence. In short, if you want to build better software, consider using TDD as part of your development process.