I came across an interesting problem recently. A UIEntity I was programming wasn’t updating its children when it updated itself. This broke code that depended on the state of those children. I coded some tests to enforce that UIEntity updating them, but the “DRY Alarm” in my head went off–this is a pattern I consistently followed. I realized I should make a base class, ComplexUIEntity, that inherited from UIEntity but had a list of children. Then it would take care of making sure that those children all got loaded, rendered, updated, whatever. Then I wouldn’t have to worry about remembering to do that myself. But this led to an interesting question: should I test it and how? The answer led me to this post’s topic: implicit, “is a” assertions.
I’m a huge fan of TDD but I prefer an approach closer to BDD than extreme programming.
Basically, I want to focus on robust tests that provide the most value and help me write code and refactor, not dogmatic tests that test beyond the point of ROI and are brittle. I believe in unit testing, but also building a testing language for your system that makes it easier to write tests. So an interesting question is–what tests /don’t/ I reccomend you write?
If you have a class inheriting from another class, and that class has certain behavior, I argue you shouldn’t have to test that you still have that behavior in the child. This is what I mean by implicit, “is a” assertions. If we know a Doberman is a dog and a dog has four legs, we shouldn’t have to test that Doberman’s have 4 legs. This means we have to be aware of the Liskov Substitution principle, which states that children shouldn’t violate expectations of their parent classes. Some may worry about what could go wrong, but I argue that it will be tested incidentally as you test code that depends on the “Doberman.” If you do have a special case where behavior breaks away from the parent, then you should test /that/, to call attention to it. If your code is sufficiently unusual that you have doubts, then you should test it in that case too. I believe you should use your judgement on what’s worth testing.
So you should allow yourself to eschew tests if you know that the code has certain properties inherently, based on membership of a class. I think there’s more to it–there’s something I’ve been grasping at about not when and to what extent you test configuration, but the relationship isn’t clear to me in words yet.