3 ms·
The key reason that works for you, which is the same conclusion I've come to from my personal experience, is rejecting the "unit" part of the unit testing dogma
by akeefer 17y ago
The key reason that works for you, which is the same conclusion I've come to from my personal experience, is rejecting the "unit" part of the unit testing dogma. My personal catchphrase is "test at the highest level of abstraction possible," i.e. test at the largest aggregation of functionality that is still well-defined and that doesn't have a combinatorial explosion that prevents you from testing it thoroughly enough.
To put it another way, test those invariants that are least likely to change in the future. The "the e-mail sending component should properly construct the headers" test is testing an invariant that's unlikely to change. The "the EmailComposer class will call the EmailHeaderConstructor's constructHeader() function" test is testing an invariant that's much more likely to change.
The problem is that many unit testing dogmatists (and the associated books and conferences) encourage people to write lots of tiny little tests for every little piece of everything, and it's those tests that kill you when you're refactoring.
If you have a logical component that consists of 10 different classes that work together, your main set of tests should be at the component level, and those classes should be treated as implementation details that are only unit tested if they themselves are complicated enough that they likely have errors that aren't caught by the larger test suite. If you go crazy and unit test all the interactions between each class within that component, then when you later decide to re-architect parts of it to improve performance or simplify the code or fix bugs or in preparation for new functionality, you end up with a bunch of tests that you have to either fix or delete.
Tests like that end up discouraging refactoring due to the friction they exert, rather than encouraging refactoring the way less-fragile tests do.