Refactoring is defined by Martin Fowler as “improving the design of existing code.” Refactoring stipulates two things: that behavior does not change, and that the design has been improved. While developers have been “cleaning up” their code from the very early days, Fowler made this a discipline that developers can collaborate within. He defined a shared way to do it. Continue reading “The Value of Refactoring Skills”
Abstract classes in languages like Java or C# serve two purposes: they create polymorphism in design, and they are a convenient place to put behavior that is common to all derived classes, avoiding redundancy.
But if all behavior in TDD needs to be tested, and if instance behavior implemented in abstract classes cannot be tested (because they cannot be instantiated), then how can we adhere to our process? Continue reading “TDD: Testing Adapters for Abstract Classes”
TDD depends on a strong connection between the automation of the test suite and the system itself. The suite should record the specification that is implemented in the system, and the connection allows this to be confirmed at any point.
The problem is automated tests pass by default. So, if errors creep into the test code that breaks the connection to the system (the tests are not really doing anything) they would still pass under most circumstances. Continue reading “Sustainable TDD: Part 3”
Project managers have to balance resources. Spending them on one thing means not spending them on another. So, when the team adopts TDD, it is understandable that attention is paid to the level of resource needed to sustain it over time.
It’s not uncommon for project managers to notice, as the project grows, that the creation of tests and their maintenance seems to be an increasingly large drain on resources. Team leads may note that the suite of tests is actually larger than the production code base, sometimes far, far larger. Continue reading “Sustainable TDD: Part 2”
TDD is typically part of an agile process. This means that we embrace change, that new requirements flow into the team’s work either on a time-boxed pulse, or through some kind of pull system (like Kanban). In TDD, a new requirement always starts out as a new, failing test or “specification.” We write the test to express the requirement before it has been fulfilled.
Then, work is done in the system to make this new test pass. Over time, however, developers begin to experience the syndrome where making the new test pass makes older tests fail. Those tests must be maintained (you cannot leave tests “in the red”) which burdens the team. This problem tends to get worse over time. Continue reading “Sustainable TDD: Part 1”
This is my 48th post in this series on TDD. I wanted to bring some of this material together and engage with the notion of TDD as a sustainable process. In this posting, I will introduce the topic, and then cover some issues that pertain to sustainability and/or the seeming lack thereof. Continue reading “TDD as a Sustainable Process: Introduction”
In TDD and Code Coverage, we established that code coverage tools do not provide useful project metrics, in and of themselves. In TDD, we don’t use code coverage tools for this purpose because we don’t need to. If all production code is written to satisfy prewritten, failing tests, then by definition, all code is covered.
Still, we do have automated tools that can measure coverage. Are they useful to a TDD practitioner? Yes they are. Here are three things they are useful for. Continue reading “TDD and Code Coverage Tools”
TDD often uses unit tests to drive behavior into the system. However, sometimes acceptance tests are used to do this. When these are automated, this can give us clues as to how to make our work in TDD more reusable.
Part of the TDD process consists of writing failing tests before the code that will eventually make them pass. Test-first alone is not TDD per se, but it is a part of it.
When tests are written before production code, this has several beneficial effects. This comes from the fact that these tests have the same orientation toward the code that client code will have in the future. Tests are, essentially, the first clients of any behaviors they drive into the system. Continue reading “TDD: Tests are Client Number 1”