Recently, I had an instant messenger conversation with my good friend Paul Laudeman regarding software testing, integration testing specifically. The following is the transcript from this conversation. Thanks to Paul for allowing me to share.
Paul Laudeman: So tell me, how do you feel about integration testing including database testing?
Daniel Bullington: Well let me step back. I feel that correct unit testing is above all else, key in any testing strategy.
Paul Laudeman: I agree with that.
Daniel Bullington: This includes correct unit testing of persistence objects <-> database with mocking etc. (that’s part one of my answer).
Paul Laudeman: Right.
Daniel Bullington: Part two: Then, integration testing is important too, but a well defined strategy for generating test data and resetting to good state is essential. This presupposes that your code base is well architected enough to facilitate both distinct testing types.
Paul Laudeman: Which I've seldom ever found to be the case but that's another story.
Daniel Bullington: In that case, you are left with "unitegration testing" - unit + integration.
Paul Laudeman: So what about testing a “feature” slice from say, your business logic all the way through to persistence logic and loading from the database where you script out your database objects and push the data in and out of the database?
Daniel Bullington: Well, integration testing is a layered phenomenon, whereas unit testing is a compartmental phenomenon. So you would in a perfect would test integration between persistence objects <-> database; then domain layer/business objects <-> persistence objects, presentation logic <-> domain/business layer...you see the pattern.
Paul Laudeman: Right, that's what I’m getting at, integration testing, between more than just one tier and/or layer, to include an external system, such as a database. In other words, to prove out that your persistence logic actually works; not that you were just lucky and got the mocking code right.
Daniel Bullington: I think you are using the conventional but incorrect viewpoint...when you say "between more than just one tier and/or layer" - you really mean integration between tiers and/or layers (and any sub tiers and/or via guilt by association). It’s incorrect to say "all" because for instance, your domain layer/business layer has no clue what is in the persistence layer (e.g. is there even a database or is it web service)...see what I’m saying?
Paul Laudeman: Agreed.
Daniel Bullington: By the sheer fact you are integration testing domain/business objects <-> persistence objects, you are testing the database too, but only as an acceptable side effect. It’s about separation of and targeted testing concerns.
Paul Laudeman: Ok, then how would we go about testing the persistence objects <-> database, or should we?
Daniel Bullington: Yes.
Paul Laudeman: That's what I was trying to ask. Sorry for the roundabout way to get to it.
Daniel Bullington: It’s like asking “Why should use interfaces and mock out dependencies?” It’s the same rationale - in a roundabout way. You integration test your persistence objects <-> database separately from the integration testing between domain layer/business objects <-> persistence objects. There can and will be nuances which can change the testing dynamics...even thought 99% of the time, if you integration test between the domain layer/business objects <-> persistence objects, you are exercising the database as well. My thought is that each integration point should be independently tested so you can also have a suite targeted to that integration point. This is again, all this in a perfect world - infinite time, people, and money.
Paul Laudeman: Absolutely agreed.
Daniel Bullington: I guess you could call me a software testing snob or "realistic fanatic".