guilty of untestability

If the class is difficult to test don’t blame your test code or deficiencies in mock/test libraries. Instead try very hard to make the class under test easy to test.

Is class hard to test? Then it’s the class itself to blame, never the test code.

The punishment is simple: merciless refactoring.

Yet so many times the test is found guilty and unjustly sentenced to refactoring or improving.

Here are some real-life examples – I saw it, I moaned, I preached (poor soul who paired with me that day):

  • Class calls static methods. New patterns of mocking static methods are introduced. Yet another mocking framework (or supporting code) is added. Instead, static class could be refactored into genuine citizen of OO world where dependency injection really does miracles.
    Ok, I didn’t really see that one. But I read about it ;)
  • Class has many dependencies. The builder is introduced to create instances with properly mocked/stubbed dependencies. The effort to refactor test code and introduce builder could be spend on splitting the class so that it is smaller, has less dependencies and doesn’t need a builder any more.
  • Class has many dependencies yet again. The test class is enhanced with bunch of private utility methods to help in setting up dependencies. Yet again I would rather split class under test…
  • Test method is huge. Test method is decomposed into smaller methods. Instead I would look at responsibility under the test. Perhaps responsibility/method under test is just bloated and solves multiple different problems. I’d rather delegate different responsibilities to different classes.

All of that goes down to very simple principles I follow.

If I find testing difficult I look for reasons in the class under test. If the test smells I look for reasons in the class under test. Class under test is always guilty until proven.

I’m not saying to stop refactoring test code, I’m saying to focus on class under test. Don’t make test code smarter if you can make the code easier to test. If you spend too much time on figuring out how to test something it means code under test sucks.

For me, the quality of the class is reflected by the clarity and simplicity of its test.

Here are some warnings you can find in the test code.

  • too big setup() method
  • too many fields
  • too big test method
  • too many test methods
  • too many private utility methods
  • too

All of them smell and require refactoring. You can refactor test code, make it smarter and better. You can also refactor code under test so that the test doesn’t have to be smart and becomes simple. Simple code doesn’t smell. Usually. ;)

5 Responses to guilty of untestability

  1. My code base is infected with the “Class calls static methods” problem. Fine. I’ll refactor those static methods onto a separate class that can be instantiated. But now I’ve violated your consistency vs. elegance rule described here:
    I’m left with code that is elegant (“testable”) in some spots but no longer consistent.

    And, by the way, my codebase is way to large to consistently apply a new non-static pattern across all the objects.

    This dilemma is why I value “inconsistently well” over “consistently wrong”. I don’t see another way out of my situation. Perhaps I could carve out sub-projects and make those internally consistent, but again I don’t really have the authority. :(

    I blogged my thoughts here a few months ago:

  2. szczepiq says:

    Fair points.

    Sometimes a rule contradicts some other rule. Sometimes one is more more important than other.
    It’s all about applying the right rule to the problem at hand.

  3. […] something is hard to test it gives excellent feedback about the quality of the code under test. If you’re a developer […]

  4. Natali says:

    All creations are the reulst of the invidual interpreting and absorbing from their wider environment. The only individual touch that is’, is the interpretation of the concept, which will differ and this is what will make the idea more individual (its execution, mode of execution/construction) and this is the only original’ element. This interpretation or expression comes close to originality, a bit like a curve (in Calculus) reaching a limit, almost touching it, but not quite but still, it’s what differentiates the Da Vinci’s from the remainder or the Homer’s from the others.

  5. continuously i used to read smaller posts that also
    clear their motive, and that is also happening with this article
    which I am reading at this place.

%d bloggers like this: