We use both (executable) specs and unit tests in some of our financial software. The specs cover business behavior, the unit tests cover code. We use other testing methods as well, such as automated integration tests, etc., but that’s not what I’m asking about here.
Sometimes I’ll be writing code which, by its very nature, I know is — and always will be — completely covered by a spec, because it is core business functionality. An example would be rounding rules.
In these times I’m conflicted between wanting to write unit tests anyway (because of a feeling that the business requirements could change, even when they seem, as in the case above, like something which will be an issue forever) and feeling like I’m wasting time writing “redundant” unit tests.
Has anyone found good rules of thumb for this?
As far as I understand above means that having unit tests in addition to executable specs won’t help in discovering bugs faster, correct?
Well given that, the only rule of thumb that comes to mind is to look at it from the perspective of some future maintainer. You know, the guy who doesn’t know you, the guy who doesn’t share your current knowledge – some guy who just got your code to deal with. How to make life easier for that guy?
Let’s see…
if I choose to write duplicate unit tests, this may confuse my imaginary future-maintainer. “Why oh why did this idiot wrote duplicate tests? What was he thinking about?”
if I decide to simply skip unit tests, this may be confusing, too. “Oh this isn’t covered by unit tests why could that be? Is it because it’s already covered by some executable spec or because someone just forgot to write a unit test here?”
In both cases the problem seems to be that I failed to reveal my intent. I failed to express the reasons why I did it one or another way. Solution is, respectively, to find a way to express my intent. For this, I’d use an annotation or self-explaining code like
Whether to use annotation or code is probably a matter of personal preference. Or a matter of team habits/practices. Just be consistent and do not mix – following the same rule of thumb “not to confuse future maintainer”.
We don’t want this guy to spend sleepless nights trying to figure hidden reasons why some parts are covered by annotations while other are served by code do we? 🙂