Don’t mercilessly refactor unit tests!
I teach TDD courses, and one of the questions that inevitably pops up is whether you should refactor your tests. When it comes to eliminating duplication in tests, my threshold is very high. By that, I mean that the most important thing to me is readability. I want to read a test like a mini story: I set this up, I execute this, I verify that.
One of the biggest annoyances I encounter with experienced TDDers is when they decompose tests to the point where you can’t see what the test is doing without bouncing around to 50 places in the code. I don’t care if I have duplicate setup for multiple tests if that setup is only 1-5 lines of code. If the entire test can be seen on the screen, then you can understand what it is doing much more easily. By eliminating duplication in test setup and verification, tests become less readable. For example, I might have to keep jumping to the top of the class (or worse yet to another class) just to see what the expected values are that I’m comparing to.
When I do eliminate duplication in tests, I try to use composed methods (with descriptive names) that are explicitly called from the test methods, rather than using methods that are automatically called by a testing framework (e.g. setup methods in JUnit); this maintains the readability of each test.
I’m not saying that you shouldn’t refactor your tests at all. I just recommend that you have a higher threshold and not be as “merciless” as you are on your real code.