Assert and the optional Message

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Mar 9 11:29:43 PST 2012


On Fri, Mar 09, 2012 at 01:37:38PM -0500, Jonathan M Davis wrote:
> On Friday, March 09, 2012 09:59:42 H. S. Teoh wrote:
[...]
> > This opens up the question of, what's the *recommended* way of
> > writing unittests that check for these sorts of stuff?
> > 
> > For example, I believe in being thorough in unit tests, so I like to
> > use them to verify that the complicated in-contract I just wrote
> > actually prevents the erroneous calls that I *think* it prevents.
> > But if catching AssertError's may leave the program in an undefined
> > state, then that pretty much invalidates any further testing past
> > that point (the program may appear to work when compiled with
> > -funittest but actually fail in release mode).
> 
> If you're testing that contracts throw when they're supposed to,
> you're going to have to be very careful. Depending on what code is
> involved, catching the AssertError could have no problems whatsoever.
> For example
> 
> assertThrown!AssertError(func(5));
> 
> void func(int i)
> in
> {
>  assert(i == 2);
> }
> body
> {}
> 
> wouldn't be a problem at all. There are no destructors, scope
> statements, or finally blocks involved. But something like
> 
> assertThrown!AssertError(foo(5));
> 
> int foo(int i)
> out(result)
> {
>  assert(result = == 2);
> }
> body
> {
>  Bar bar;
> 
>  return i;
> }
> 
> could have issues if Bar has a constructor than needs to run. You just
> need to understand that destructors, scope statements, and finally
> blocks are not guaranteed to be run if an Error is thrown and avoid
> catching Errors in cases where they'd be skipped (or know enough about
> the state that the program would be in if they _were_ skipped to know
> that it's not going to cause problems).
> 
> Personally, I think that checking contracts is overkill, but you can
> do it if you're careful.
[...]

Hmph. Well, then that defeats the purpose of checking contracts, because
checking contracts is only justifiable if it's complex enough, which
means that it's liable to involve things like dtors and scope
statements.  It's silly to want to check a trivial contract like
assert(x>0);, because if something *that* simple can go wrong, then so
can the unittest, so you're not proving anything at all.

But this isn't that big a deal. One could argue that if a contract is
convoluted enough to warrant a unit test, then perhaps most (or all) of
its complexity should be factored out into a separate, unit tested
function, which is then just invoked from the contract.

(I find this a bit ironic, since TDPL states that the reason contracts
allow statements is so that complicated conditions can be tested for,
rather than being limited to just a single expression, as is the case in
most other languages that support DbC. Now it seems that simple
contracts are the way to go.)


T

-- 
MASM = Mana Ada Sistem, Man!


More information about the Digitalmars-d-learn mailing list