Testing: Avoid setUp and tearDown

In Let your examples flow, Dan North describes how “Don’t Repeat Yourself” (DRY) isn’t necessarily the most important guideline for tests. While I agree with his conclusions, I think the DRY principle is still extremely important for tests.

Dan’s point is that the most important attribute of tests is that they can be read like a story. “Store a page with the text ‘foo’ in the database, simulate a web request, check that the word ‘foo’ is present in the response”.

What would happen if “store a page with the text ‘foo’ in the database” was refactored out to a setup method (or a constructor)? The test would dump us into the middle of the story. In medias res is a well know technique for fiction. It’s not as useful for software.

So Dan recommends against overapplying “Don’t Repeat Yourself” in tests.

I would echo this recommendation, but not quite. Anyone who has maintained a large suite of unit tests knows that duplication can be devastating for maintainability. So I often have custom “assert” methods (assertNoErrors(ProcessedEntity) is my favorite), I make sure my domain objects are easy to construct from test, and sometimes, I construct classes which are only used to support tests.

The important fact is that this reused code is called directly from the flow of the test method and the names of the methods and classes have been chosen carefully to ensure that the tests read well.

So: Do follow the DRY principle in tests. But do avoid “magical” setup methods.

Copyright © 2008 Johannes Brodwall. All Rights Reserved.

About Johannes Brodwall

Johannes is Principal Software Engineer in SopraSteria. In his spare time he likes to coach teams and developers on better coding, collaboration, planning and product understanding.
This entry was posted in Java. Bookmark the permalink.
  • http://andersnoras.com Anders Norås

    Agreed! I often find myself refactoring setup methods to factories called by the individual tests whenever I come across tests that need to do some prep work before they can run. Makes things much easier to grasp when you revisit the test fixtures later.

  • Christian Rørdam

    Agreed! I think it is important that a test method can be read as a sequence of steps, but the steps can be reusable methods. So I do extract the gory details of actually performing the step, but I usually don't extract a subsequence of steps as a new method. And of course, I try to give the methods as good names as possible, as always.

  • http://andersnoras.com Anders Norås

    Agreed! I often find myself refactoring setup methods to factories called by the individual tests whenever I come across tests that need to do some prep work before they can run. Makes things much easier to grasp when you revisit the test fixtures later.

  • Christian Rørdam

    Agreed! I think it is important that a test method can be read as a sequence of steps, but the steps can be reusable methods. So I do extract the gory details of actually performing the step, but I usually don’t extract a subsequence of steps as a new method. And of course, I try to give the methods as good names as possible, as always.