This is the 4th part of the series about analyzing our code and deciding what to test. Last time, we talked about design constraints.
Now we’re moving towards the code itself. Almost there.
Step 6: Prepare existing code
This is an obvious step in test-after. We want to test the existing code, and therefore we need to see what we’re testing.
In addition, we need to refactor the code in order to test it, as we’ve seen in step 4. We need to introduce the seams, isolate the actual parts that we want to test and clear the way from dependencies.
Since the code is already written, we assume it is bound already by the design constraints we investigated in step 5. However, if we’re refactoring, we still need to adhere to those constraints in some level. For example, if we implemented a derived class, bound by its base, it may be easy to test the new code in a separate class with less dependencies. The derived class will call the newly extracted, and more easily testable class.
In TDD, things are obviously different. Our code preparation is really identifying boundaries. We know how our new code is going to fit within the design constraints. In that last example, we know we need to write a derived class, but it may be easier to test-drive an internal class, that the derived class will call.
Note that in TDD, we’ll finish the bridges or adapters later, after we’ve done with the design and the tests. Which is finally, the next step.
Step 7: Write the tests
That’s pretty much self explanatory. Although I’d like to mention one thing that always happens during this process, regardless of TDD or test-after.
After all the preparations we’ve done, there are still cases we think of during the process of writing tests. We might think of other cases, or we discover a problem in the design or code that needs fixing.
In TDD, cases we didn’t think of pop up all the time. That’s where emergent design comes from. In test-after, when we’re moving stuff around, we identify problems, or tests we’d like to write to confirm we haven’t broken anything.
This is where the linear form of the process stops. We don’t always need to go back to the beginning, but we need to consider the new cases we found and their impact on how to test, design constraints and testability.
We’ll finish the series in the next post.