How do you test pre-/post-conditions and invariants?

Magnus Lie Hetland magnus at hetland.org
Sat Feb 26 03:24:15 PST 2011


On 2011-02-26 01:20:49 +0100, Jonathan M Davis said:

> So, using such assertions makes good sense when you control
> both the caller and the callee and it's something that should never happen.

Yeah, in my case that's what's going on. I'll only be using the 
contracts during testing anyway, and remove them with -release in the 
code that's actually to be used. (The code is part of some benchmarking 
experiments, so I'd rather not have any kind of checking like that when 
running those.)

> However, if you don't necessarily control the caller or if it's something that
> _could_ happen at runtime (even if it shouldn't), then an exception makes a lot
> more sense.

OK. I had the impression that using assert() in contracts was standard, 
also for API functions. I thought contracts fulfilled a similar sort of 
function to assert(), in that they're removed in release code -- as 
opposed to enforce(), for example...? I'm guessing that if I released a 
binary version of a library, I wouldn't leave the contracts in? Or 
perhaps I would (but, as you say, with exceptions)? Depends on the 
situation, perhaps?

What kind of exceptions would be most relevant to indicate a contract 
failure (if the contracts are made part of the API)?

> I tend to view exceptions as part of the API and think that they should be
> tested. Assertions, on the other hand, aren't really part of the API, 
> since they
> go away in release mode, and I therefore view them as test code. They're
> verifying that your logic is correct.

Exactly. The same, of course, applies to contracts -- which is why I'm 
a bit confused by your suggestion to use exceptions in them.

Or perhaps I'm misreading you completely, and you're only suggesting 
that I use code paths that throw exceptions in the function body 
itself, e.g., with enforce(foo, exception) (which would make sense to 
me)?

> So, on some level, it is indeed a stylistic thing, but where you choose to use
> exceptions and where you choose to use assertions can have a big effect on code
> that uses your code.

Sure thing. It just seems to me that contracts and assertions go well 
together, and have the same function, of testing your program logic?

I guess the driving force of my original query was the old "first, see 
your test fail" idea of test-driven programming. If I just slap a 
precondition on some code, it won't fail because things aren't 
implemented properly yet (as a normal unit test would) -- I'd actively 
have to implement a call to it *improperly*. It just seemed naturally 
to me to do that as part of the test code, rather than a one-off thing 
in the main code.

However, I could always add a call to my unit test, run it, and see it 
crash -- and then comment it out. Doesn't seem like the prettiest way 
to handle things, but it's OK, I guess together with the idea of making 
the contracts super-simple (and to test any functionality they use 
separately).

[snip]
>> 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 ;)
> That's probably a good way to handle it .

OK, good :)

-- 
Magnus Lie Hetland
http://hetland.org



More information about the Digitalmars-d-learn mailing list