Does unit testing lead to premature generalization (specifically in the context of C++)?
- by Martin
Preliminary notes
I'll not go into the distinction of the different kinds of test there are, there are already a few questions on these sites regarding that.
I'll take what's there and that says: unit testing in the sense of "testing the smallest isolatable unit of an application" from which this question actually derives
The isolation problem
What is the smallest isolatable unit of a program. Well, as I see it, it (highly?) depends on what language you are coding in.
Micheal Feathers talks about the concept of a seam: [WEwLC, p31]
A seam is a place where you can alter behavior in your program without editing in that place.
And without going into the details, I understand a seam -- in the context of unit testing -- to be a place in a program where your "test" can interface with your "unit".
Examples
Unit test -- especially in C++ -- require from the code under test to add more seams that would be strictly called for for a given problem.
Example:
Adding a virtual interface where non-virtual implementation would have been sufficient
Splitting -- generalizing(?) -- a (smallish) class further "just" to facilitate adding a test.
Splitting a single-executable project into seemingly "independent" libs, "just" to facilitate compiling them independently for the tests.
The question
I'll try a few versions that hopefully ask about the same point:
Is the way that Unit Tests require one to structure an application's code "only" beneficial for the unit tests or is it actually beneficial to the applications structure.
Is the generalization code need to exhibit to be unit-testable useful for anything but the unit tests?
Does adding unit tests force one to generalize unnecessarily?
Is the shape unit tests force on code "always" also a good shape for the code in general as seen from the problem domain?
I remember a rule of thumb that said don't generalize until you need to / until there's a second place that uses the code. With Unit Tests, there's always a second place that uses the code -- namely the unit test. So is this reason enough to generalize?