Skip to content

Testability

sandal edited this page Jan 3, 2012 · 9 revisions

We all know how important testing is, but it isn't sufficient to simply have good test coverage. It is necessary to also keep a keen eye on writing implementation code that is highly testable. This prevents our tests from becoming overly complicated, and reduces their brittleness and maintenance overhead. The best way to improve your code's testability is to do so by design, and few concepts have influenced my thinking about that more than the SOLID principles.

I've already discussed SOLID at length in Practicing Ruby 1.23, and that's where you should look if you want to know about the principles in detail. However, a quick look at the kinds of examples that article covers will give you a glimpse at how SOLID can be used to improve the testability of your code:

  • Simplifying a complex object with a ton of state and functionality by extracting new objects that have a single purpose.

  • Using module mixins at the instance level to implement decorators rather than reopening a class and adding methods to it.

  • Using dynamic delegators as an alternative inheritance that reduces the risk of method definitions clashing with one another.

  • Using dependency injection / duck typing to reduce code brittleness.

Through the application of the SOLID principles, code becomes more testable because it becomes more loosely coupled. This makes coding to an interface rather than an implementation easier, and also makes isolating discrete units of code to test less challenging. Most code that is hard to test is likely to be in violation of at least some of the SOLID principles, and resolving those violations will almost certainly make things go more smoothly. That means that if you're fighting against your tests, it may be a sign your code isn't SOLID enough.


Turn the page if you're taking the linear tour, or feel free to jump around via the sidebar.