Unit tests and verifying pre/post-conditions and invariants

Lutger lutger.blijdestijn at gmail.com
Sun Aug 15 15:06:12 PDT 2010


Jonathan M Davis wrote:

> Is there a standard and/or acceptable way to make sure that pre-conditions,
> post-conditions, or invariants _fail_ when running unit tests? That is, lets
> say I had a function like this
> 
> void func(int x)
> in
> {
>     assert(x < 8);
> }
> body
> {
>   //...
> }
> 
> 
> and I wanted to test to make sure that func() couldn't be called with any int
> greater or equal to 8, what would I do? The best that I can think of is to
> catch an AssertError and ignore it. e.g.
> 
> unittest
> {
>     try
>     {
>         func(8);
>         assert(0);
>     }
>     catch(AssertionError ae)
>     {}
> }
> 
> 
> But catching AssertionErrors is generally a bad idea. As I understand it, when
> anything derived from Error is thrown, code is not left in a proper state,
> with stuff like destructors being skipped. Would it be okay to catch it in a
> case like this, or is it a really bad idea? If it's a bad idea, I haven't a
> clue how to verify that pre-condition, post-conditions, and invariants are
> correct.
> 
> - Jonathan M Davis

Thats a good one. It used to be so that dmd would assume a halt and you could 
get segfaults for continuing on. I *believe* this has changed and it is ok to 
catch AssertError in this scenario. The only thing I can think of is that 
nothrow functions can be optimized by the compiler, but are not typechecked for 
throwing Error. 

Even if this is correct, you still have the problem foo could call other 
functions that assert, which invalidates at least two contract checks. This may  
require some care. Perhaps an idea is to define a PreconditionError and 
PostconditionError and wrap them in a function similar to enforce, so you can 
differentiate more easily where the error is coming from. This way you also get 
better error messages and have one point where to change the behavior if this 
may be required.


More information about the Digitalmars-d-learn mailing list