I've worked with lots of great developers that would see so much as a line of duplication and take it upon themselves to drop everything, including the donut in their hand, to remove it from code. However, when it comes to test code, that same developer would shrug their shoulders and say: 'It's only test code'. I just don't get this. If lack of reuse and duplicate code would cause an aneurysm in normal code, why is it acceptable in test code? For that matter, why would the way you treat test code be any different at all?
When we write unit tests, it's code we intend to last just as long as the class it's testing, or at least until the assumptions we made about the code have changed. And given how slowly some companies could change even those basic assumptions, that could mean never. Testcode still needs to be easy to maintain, and easy to understand.
Here's some of the reasoning I've heard:
I don't want to make the unit test complicated, it should be easy to understand the intention
If abstractions and code reuse done properly can make code easier to understand, why would the same not apply to test code? How would duplication between two unit test classes aid in the clarity of the individual test?
Unit tests should be completely isolated from each other
I'll agree to this in principle. But I think it can be taken too far. Unit tests should be able to be run side effect free. You should be able to run each individual test by itself, or with any number of other unit tests without the existence or absence of such tests causing failures. However, this has nothing to do with sharing abstractions with each other, or reusing the same setup data if more than one class under test uses the same domain objects. As long as you're creating new instances in your test classes, and not accessing them through stateful static calls, there should be no issue.
Modifying one test to pass shouldn't cause another to break
This is a tricky one that has bitten me numerous times before. If you create some kind of abstraction, such as some type of a builder to create a set of test data for multiple tests, you run the risk of breaking a lot of tests if you change something in the builder to make one pass. It can be extremely disheartening to watch the unit test you were working with pass, only to see hundreds of test failures when you run the entire build.
However, despite the pain this has caused me in the past, doesn't this seem like a normal coding problem? Maybe it's coupling/cohesion, or demeters law, or any other random law. There's probably a perfectly well known refactoring mechanism to make this test code easier to modify without side affects. There is no reason not to apply them to your unit test code as well.
Now though, there comes the dirty part, that only an 'Enterprise' developer will know the unfortunate reality of. What if your test code looks nothing like your real code, but there's nothing really wrong with it except it breaks many of the largely nonsensical 'coding standards' put in place by some type of 'governing body'? What if *gasp* its better as a result?