Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TDD - When introducing a class when refactoring - should that class be unit tested?

Presume you have a class which passes all its current unit tests.

If you were to add or pull out some methods/introduce a new class and then use composition to incorporate the same functionality would the new class require testing?

I'm torn between whether or not you should so any advice would be great.

Edit:

Suppose I should have added I use DI (Dependency Injection) therefore should I inject the new class as well?

like image 388
Finglas Avatar asked May 19 '09 21:05

Finglas


3 Answers

Not in the context of TDD, no, IMHO. The existing tests justify everything about the existence of the class. If you need to add behavior to the class, that would be the time to introduce a test.

That being said, it may make your code and tests clearer to move the tests into a class that relates to the new class you made. That depends very much on the specific case.

EDIT: After your edit, I would say that that makes a good case for moving some existing tests (or a portion of the existing tests). If the class is so decoupled that it requires injection, then it sounds like the existing tests may not be obviously covering it if they stay where they are.

like image 180
Yishai Avatar answered Oct 02 '22 15:10

Yishai


Initially, no, they're not necessary. If you had perfect coverage, extracted the class and did nothing more, you would still have perfect coverage (and those tests would confirm that the extraction was indeed a pure refactoring).

But eventually - and probably soon - yes. The extracted class is likely to be used outside its original context, and you want to constrain its behavior with tests that are specific to the new class, so that changes for a new context don't inadvertently affect behavior for the original caller. Of course the original tests would still reveal this, but good unit tests point directly to the problematic unit, and the original tests are now a step removed.

It's also good to have the new tests as executable documentation for the newly-extracted class.

like image 20
Carl Manaster Avatar answered Oct 02 '22 15:10

Carl Manaster


Well, yes and no.

If I understand correctly, you have written tests, and wrote production code that makes the tests pass - i.e. the simplest thing that works.

Now you are in the refactoring phase. You want to extract code from one class and put it in a class of its own, probably to keep up with the Single Responsibility Principle (or SRP).

You may make the refactoring without adding tests, since your tests are there precisely to allow you to refactor without fear. Remember - refactor means changing the code, without modifying the functionality.

However, it is quite likely that refactoring the code will break your tests. This is most likely caused by fragile tests that test behavior, rather than state - i.e. you mocked the the methods you ported out.

On the other hand, if your tests are primarily state-driven (i.e. you assert results, and ignore implementation), then your new service component (the block of code you extracted to a new class) will not be tested. If you use some form of code coverage testing tool, you'll find out. If that is the case, you may wish to test that it works. Might, because 100% Code Coverage is neither desirable nor feasible. If possible, I'd try to add the tests for that service.

In the end, it may very well boil down to a judgment call.

like image 23
Assaf Stone Avatar answered Oct 02 '22 14:10

Assaf Stone