- Designing testable code at the architectural, design, and implementation levels
- Understanding the Hexagonal Architecture, dependency injection, observability, and controllability
- Avoiding testability pitfalls
I usually say that every software system can be tested. However, some systems are more testable than others. Imagine that for a single test case, we need to set up three different web services, create five different files in different folders, and put the database in a specific state. After all that, we exercise the feature under test and, to assert the correct behavior, again need to see if the three web services were invoked, the five files were consumed correctly, and the database is now in a different state. All those steps are doable. But couldn’t this process be simpler?
Software systems are sometimes not ready for or designed to be tested. We discuss some of the main ideas behind systems that have high testability. Testability is how easy it is to write automated tests for the system, class, or method under test. We saw that by allowing dependencies to be injected, we could stub the dependency. This is about other strategies you can use to make testing easier.
The topic of design for testability deserves an entire book. I cover several design principles that solve most of the problems I face. When presenting these principles, I will discuss the underlying ideas so you can apply them even if the code changes you must make differ from my examples.
Design for testability is fundamental if our goal is to achieve systematic testing—if your code is hard to test, you probably won’t test it. When do I design for testability? What is the right moment to think about testability? All the time. Much of it happens while I am implementing a feature.
You should design for testability from the very beginning, which is why I put it in the “testing to guide development” part of the flow back in chapter 1, figure 1.4. Sometimes I cannot see the untestable part during the implementation phase, and it haunts me during the test phase. When that happens, I go back to my code and refactor it.
Some developers argue that designing for testability is harder and costs too many extra lines of code. This may be true. Writing spaghetti code is easier than developing cohesive classes that collaborate and are easily tested. One of the goals of this chapter is to convince you that the extra effort of designing for testability will pay off. Good, testable code costs more than bad code, but it is the only way to ensure quality.
Leave a Reply