In my last blog I described an approach to testing which i called 'Integration Unit Testing'. The basic idea was to unit-test a class against its real-life environment rather than relying on a mocking infrastructure. I cannot tell whether and when this approach is good to follow - i guess that it is a question of personal taste and intuition, as are many aspects of programming.
Another approach i would like to address, this time briefly, is the one of 'Integration Testing instead of Unit Testing'.
In a nutshell, here's what this is about:
You are given some tack to accomplish. First you write classes ImportantClass and classes B and C. Class ImportantClass does some importantStuff(), and with the aid of classes B and C seems to get the job done. Being a TDD guy, you of course beforehand write the unit tests for B, C and ImportantClass.
A few hours/days later, you discover that what you came up with is bullcrap and decide to revert your changelist. You write some new Aid classes D and E, and alter class ImportantClass to use them. Of course, BTest and CTest are no longer relevant, and you have to write DTest and ETest in their place.
Now the real bad thing is that ImportantClassTest is also no longer valid. The problem is that, being a unit test, in its bulk it does not assert that some high level business functionality is achieved. Rather, it very much asserts that e.g. some methods of B and C are called with some parameters.
Being a patient guy, you say: 'O.K. Patience my young padawan'. (You say it to yourself, knowing it is healthy for a programmer to talk to themselves.) So you rewrite the ImportantClassTest.
Of course, a day later you have another ephiphany and discover that the concept of classes D and E is bullcrap also. So you do another revert and end up in the same ordeal, rewriting again ImportantClassTest, and very much wanting to bite off your arms now.
If you end up in such a situation, where classes B,C,D, E and so forth are likely to change/drop with each ephiphany you have or each new developer working on the code, it is likely an indication that classes B,C and so forth are not key aspects to the business functionality to begin with. If they are not, perhaps the effort is not worth to unit-test them at all. So what you could do is write an ImportantClassIntegrationTest, test only thru the ImportantClass's public API and assert some business objectives are really achieved. Then you measure the test's code coverage against the code of ImportantClass and the current B, C and so forth classes. If the metric is OK, you also have done OK.
To further emphasise on the small importance and transient-ness of the B and C and so forth classes, you can either:
- nest them inside the ImportantClass
- create them inside the package of ImportantClass and give them package visibility.