2025 Public Training Schedule
January 14 – 17, 2025 – Agile Analysis and Design Patterns – Half-Day Sessions
(c) 2024 To Be Agile
I’ve built my career on writing software to automate other industries. I’ve learned a lot about a range of disciplines and businesses, how they operate, and very often their “secret sauce” can be embodied in the software that they write to run their businesses.
I believe that the quality of our build and the quality of our software, in general, have a huge dependency on the quality of our tests. In test first development the tests are our plan for implementing a behavior.
Writing tests well is a critical skill that I don’t see enough developers possess. Anyone can write a test but writing a good test requires a great deal of skill. It’s not just that a test is unique and fails for only one reason but a test also has to validate behaviors in an implementation-independent way so that we have the freedom in the future to refactor our code and not make our tests break.
This requires conceptualizing the software that we want to build at a higher level that makes it far more extensible. All of these magical things happen when we start to do test-first development but very often we don’t talk about them and so these benefits aren’t consciously recognized.
I find that when I do test-driven development well I am able to build features and validate them while still retaining the freedom of changing my designs in the future without breaking my tests. This makes my tests “open for extension” so that they support me when I refactor my code. Refactoring is when I want my tests to support me the most and it all comes from writing good implementation-independent tests.
But how do we do this? How do we get clear on writing the correct number and kind of unit tests for any behavior that we might want to create? The answer to that question is to think of tests and the assertions we create in our unit tests as a form of specifying the behavior we want our code to have. We call this “test as spec” and it is a way of thinking about our unit tests as a form of specifying the behavior we want to create.
I don’t put any code into my system without making a failing test pass so when I want to add code to my system I have to ask myself what test I need to write in order for me to have a reason to create the behavior to make this test pass.
So good tests not only support refactoring but also support helping me think about my features at the right level of abstraction. This allows me to encapsulate functionality, forge better method signatures, and generally produce higher-quality code. These are just some of the unspoken benefits of having well-written automated unit tests.
Previous Post: « Avoid Branching
Next Post: Identify Areas of Risk »