I wrote this class that does a few things (perhaps this is a violation of the Single Responsibility Principle). I realize now that some other part of the project needs a piece of that logic and the way I’m going to expose it is to extract a class out of my original System Under Test.
I anticipate being able to do this without having to change any test code, but when I finish, you could argue that the test isn’t a unit test anymore. It’ll be testing the original class and the class I’ve extracted. In other words, I’ll have one test case, but two systems under test.
Am I supposed to refactor my test code after I’m done? IE: Create an ExtractedClassTest and move all the relevant tests from OriginalClassTest into it? This seems like it could be a little risky: I may lose some coverage in the process, it may not be as simple as moving a test and I’d end up rewriting some test code that I know used to work but may not anymore, etc.
On the other hand, if I leave the OriginalClassTest as-is, I can see this being a test maintenance issue. It’ll be a little confusing to find where the ExtractedClass’s tests are. Your first impression will be that it doesn’t exist. Over time with lots of production code refactorings, this could become a serious issue.
I’m new to TDD so I’d like an expert’s advice. Thanks!
For the duration of the development, have both. Keep the old tests as assurance that you haven’t broken anything, write new tests (from scratch) to help you design the classes as they should be.
At the end, run through and remove anything that’s defunct in the old tests. Be careful in this analysis; don’t remove something because you think it should be defunct. Demonstrate to yourself (or someone else, or a rubber duck) why it isn’t needed any more. Break the test and make sure that another test breaks with it.
Anything that’s left in the old tests should be taken on a case-by-case basis, but mostly they should be rewritten into the new structure.
Because you’re right, you don’t want to get left with a maintenance nightmare. But you don’t want less path-coverage than you had before.
4
After watching this amazing talk “Ian Cooper: TDD, where did it all go wrong”, I’m going to disagree with @pdr. I think you should only keep the original tests. Your ability to refactor your system under test without breaking, writing or changing any tests is the whole purpose of writing tests in the first place.
If I were to test the extracted class, I’d be testing the implementation rather than the behavior. As a result, my code would be more difficult to refactor in the future: These new tests would likely fail even if the behavior still worked.