3 Reasons Why It’s Important to Refactor Tests 

 February 9, 2016

by Jon Reid


You may have seen the 3 steps of “the TDD waltz”: Fail, Pass, Refactor. There are many ways to do it wrong! Two common mistakes are:

  • Skipping the refactoring step
  • Not skipping it, but refactoring only production code

So let me give you 3 reasons why it’s important to refactor tests.

[This post is part of the series TDD Sample App: The Complete Collection …So Far]

1. Tests Are Code, Too

Test code isnt the forgotten cousin of production code. In fact, good tests are more valuable than production code. If you have a rich suite of tests, you can derive production code that satisfies them. But going the other way—deriving test code from production code—is much harder.

Like any code, tests can rot if neglected. Treat test code with the same respect you give to production code. If you refactor production code, why wouldnt you refactor tests?

(You do refactor production code, dont you? And I dont mean “changing things” or “rewriting.” I mean real refactoring, by the book.)

Treat test code with the same respect you give to production code.

Click to Tweet

2. Tests Should Be Readable

As with any code, readability is vital. Why? Because code isnt just for computers; its for people. Think of the next person who will have to read your tests. (…That person may be you! In which case, youre doing your future self a favor.)

A big part of readability is hiding details in methods with well-chosen names. Good names express what something does, or why. The details of how are there in the method, but only if you need to see them.

Refactor tests to have good names, good variables, and well-named helper methods. The better a test expresses itself, the less trouble youll have maintaining it.

3. Tests Should Be Easy to Update

Production code keeps changing. When that happens in a way that requires tests to also change, which would you rather do?

  • Update 20 different tests.
  • Update 1 helper method used by 20 tests.

Some people say that test code shouldnt be DRY (Dont Repeat Yourself). There is a balance to hit: test code shouldnt have layers upon layers of abstractions. But that shouldnt be an issue, because good test code is simple to begin with:

  • No conditionals
  • No loops (except rarely, for repeating calls)

So Ive found that one layer (occasionally two) of small helper methods helps keep tests easy to maintain.

Refactor Tests: Because Its All Refactoring

Renaming, moving things around, extracting methods… This is all basic refactoring that applies to any code, including test code. So dont be afraid to refactor tests.

Next time, Ill show you 3 steps to apply when refactoring tests.

Are your tests “set and forget”? When was the last time you refactored any tests? Share your thoughts, experiences, and questions in the comments below.

[This post is part of the series TDD Sample App: The Complete Collection …So Far]

Jon Reid

About the author

Programming was fun when I was a kid. But working in Silicon Valley, I saw poor code lead to fear, with real human costs. Looking for ways to make my life better, I learned about Extreme Programming, including unit testing, test-driven development (TDD), and refactoring. Programming became fun again! I've now been doing TDD in Apple environments for 20 years. I'm committed to software crafting as a discipline, hoping we can all reach greater effectiveness and joy. Now a coach with Industrial Logic!

  • I always find myself with a lot of dublicate testing code. Mainly due to the fact, that tests should be independant from one another. So for example if my app contains two UITableViewController-Subclasses, I will have two TestClasses for that. Both will contain Testcases like:


    Is there some refactoring possible I am missing out?

    • Timm, I guess it depends: How much duplication is there, really? Not just in the test cases (shown by the names you list) but in the test code itself.

      If you have truly duplicated tests, then you could pull them to a base class. But should you? A common refactoring rule-of-thumb is “3 strikes and you refactor.” So for two sets of similar tests, I’d shrug. For three, I’d extract them.

      Then I’d look for parallel refactoring opportunities in the production code.

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}