Unit tests makes it harder to refactor code

During my recent brownbag on TDD one comment was that having a lot of unit tests makes it harder to refactor code. First of all the word refactoris in my opinion misused as much as mocking. There is a difference between refactoring and rewriting. Refactoring means you change the code to be “better” without changing any functionality. Rewriting means you potentially change things completely including changing interfaces in APIs. So first of all, if you refactor your code and that means you have to change your unit tests your unit tests are too tightly coupled with your code. Lesson learned; somebody screwed up when writing the tests in the first place. This happens all the time when you learn TDD. It is just a matter of biting the bullet and learn form the mistake you made.

So back to the original statement; it should really be unit tests makes it harder to rewrite code. Think about it. You want to change an API and some functionality and as a result of that you have to update hundreds of unit tests. That’s a big pain right? But wait… All these tests that now fail means I have manually verify that things I didn’t want to change still works and things I wanted to change are changed to the correct thing. That is all good isn’t it? All the failing unit tests are really like a buddy asking; Did you really want to change this? Is it really a good idea to change this? Consider the alternative with no unit tests… Sure you don’t have to “waste time” updating old unit tests but neither do you know if your code works as expected.

So if you’re ending up changing tests when you refactor code; somebody screwed up. And changing unit tests when you rewrite code is a good thing!

Comments (8)

  1. Good unit tests are atomic, so if a change surface is small and code written following SOLID principles etc. the number of tests shouldn't be large…

    Other then that small comment, +1

  2. I've heard that, too, but I think that any pain you feels when "refactoring" your code is more of an issue with following good programming principles than the fact that the code is wrapped in unit tests.  If one's not following good programming principles like the Open Closed Principle or Single Responsibility Principle, changing your code is still incredibly easy because each change probably won't go beyond one or two small classes.  And if the change is substantial, you can simply eject the old code and tests and start new, pulling in whatever small classes from the old code that you can.

    After doing TDD for a while, I've learned that it's not enough.  It's essential, but I've seen/written some big messes with TDD.  But when coupled with following principles like SOLID, you'll really see good results.

  3. Anonymous says:

    I have to wonder how you structured your code, and your tests for this to happen…

  4. cellfish says:

    …for what to happen? Easy or hard to refactor? 🙂

  5. Ben Boyter says:

    Totally agree. I am sick of people complaining that TDD makes refactoring difficult. If it makes it difficult then you are doing it wrong. Tests that break because you change code is a good thing! Thats where the test adds value. If tests unrelated to the code you are working on break that means your tests are crap or your design is crap!

    Alas the crusade against brittle tests is a long and slow one 🙂

  6. Agreed!

    But I think you could change the title a little bit. I came to the site thinking that you were actually complaining about TDD.

    Nice post, btw!

  7. cellfish says:

    @Gregorio: maybe that was the point… 🙂

  8. Bubak says:

    You can choose which unit tests to keep and which not. I usually keep higher level tests.