How do you test pre-/post-conditions and invariants?
Magnus Lie Hetland
magnus at hetland.org
Fri Feb 25 14:33:20 PST 2011
On 2011-02-25 20:04:10 +0100, Jonathan M Davis said:
> On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote:
>> Or, more generally, how do you test asserts (which is what I'm using in
>> my preconditions etc.)?
>>
>> As far as I can see, collectException() won't collect errors, which is
>> what assert() throws -- so what's the standard way of writing unit
>> tests for preconditions that use assert? (I.e., test that they will, in
>> fact, throw when you break them.)
>
> I think that the reality of the matter is the most of the time people _don't_
> check them. And on some level, it doesn't make sense to. It's kind of like
> asking how people test their unit tests. Unit tests are already testing
> code. Do
> you want to be testing them on top of that? And if you do, do you test _that_
> code? Where do you stop?
I guess so. But you could say the same thing about other cases where
you throw an exception when you detect that something is wrong -- but
those are normally tested, right? Also, the difference here is that the
precondition is written as a general "test", whereas my actual test
would have specific cases.
For example, I have a test that checks that I don't add the same object
twice to some structure, and the check involves some traversal -- code
that could potentially be wrong. I wanted to make sure that it wasn't
by explicitly adding the same object twice -- code (i.e., my unit test)
that most likely could not be wrong.
But I do see your point.
[snip]
> And testing post-conditions and invariants in the manner that you're trying to
> do borders on impossible. What are you going to do, repeat the
> post-condition or
> invariant test on the result of the function or on the state of the object that
> the function was called on after the function was called? That's just doing the
> test twice.
Right.
> You might as well just re-read the post-conditions and invariants to
> make sure that you wrote them correctly.
>
> I do see value in testing pre-conditions if you're using exceptions rather than
> assertions (which means that you're not use in blocks). In that case, you're
> testing the API to make sure that it does what it's supposed to do. But if
> you're dealing with assertions, then it's really test code as opposed to API
> code, and I don't see the same value in testing that. You'd just be
> testing test
> code.
OK. For the practical reason, I refer you to my explanation above. But
I guess it's a style issue -- and I'm fine with not testing these
things, by all means.
[snip]
> Those changes _do_ make it so that you can use collectException to
> collect an Error (though it defaults to catching Exceptions only), but
> they also
> include assertThrown and assertNotThrown which effectively assert that the
> Exception or Error that you expected to be thrown (or not) from a particular
> expression or function call was indeed thrown (or not).
> So, you _can_ use that with AssertError to verify your pre-conditions.
OK, thanks.
> However, I would point out that catching Errors is generally a _bad_ idea.
[snip lots of useful stuff]
Thanks for educating me :D
I guess the conclusion will be that I'll focus on keeping my
preconditions really simple. (And any utility functions I use in them
can then get unit tests of their own instead ;)
--
Magnus Lie Hetland
http://hetland.org
More information about the Digitalmars-d-learn
mailing list