throws(statement, ErrorType)

Jonathan M Davis jmdavisProg at gmx.com
Sun Jan 23 04:05:38 PST 2011


On Sunday 23 January 2011 03:55:48 spir wrote:
> On 01/23/2011 12:36 PM, Jonathan M Davis wrote:
> > On Sunday 23 January 2011 03:14:48 spir wrote:
> >> On 01/23/2011 06:32 AM, Jonathan M Davis wrote:
> >>> On Saturday 22 January 2011 20:45:14 Andrej Mitrovic wrote:
> >>>> *There are several of those, like assertExcThrown, etc. Try searching
> >>>> the newsgroups for std.unittest or std.datetime and there should be a
> >>>> link to the source if you want it right now.
> >>> 
> >>> It's currently being reviewed and eventually vote on in the
> >>> "std.unittests for (final?) review" thread (which reminds me that I
> >>> need to finish my updates to put the next version up - though IIRC,
> >>> it's primarily a documentation change, not an API change). From the
> >>> looks of it, I expect it to pass the vote (for which Andrei set the
> >>> deadline as Feb 7), at which point it looks like those functions will
> >>> be going into std.exception. So, assuming that it passes the vote and
> >>> there's no release between now and then, then it'll be in the next
> >>> release.
> >>> 
> >>> assertThrown is the current name of the function that spir is looking
> >>> for.
> >> 
> >> Thank all for your answers. Seems I'll have to wait a bit.
> >> Pointer to the current code?
> >> (I'm very curious of how assertThrown works, actually asked about
> >> throws(statement, ErrorType) because I have no idea how to craft it
> >> myself. Seems to me needs compiler support to pass around the
> >> statement. Please, do not tell me it uses string mixins ;-)
> > 
> > It uses lazy, not string mixins. It was a fair bit of work to figure out
> > though, and it has had several incarnations (one of which _did_ use
> > string mixins). However, the current version is quite clean IMHO. The
> > current code can be found here: http://is.gd/jZEVl
> > 
> > However, I'll be posting an updated version for further review relatively
> > soon. If all you really want is to see the code for assertThrown though,
> > it's fairly short and simple:
> > 
> > void assertThrown(T : Throwable = Exception, F)
> > 
> >                   (lazy F funcToCall, string msg = null, string file =
> >                   __FILE__,
> > 
> > size_t line = __LINE__)
> > {
> > 
> >      bool thrown = false;
> >      
> >      try
> >      
> >          funcToCall();
> >      
> >      catch(T t)
> >      
> >          thrown = true;
> >      
> >      if(!thrown)
> >      {
> >      
> >          immutable tail = msg.empty ? "." : ": " ~ msg;
> >          
> >          throw new AssertError(format("assertThrown failed: No %s was
> >          thrown%s",
> > 
> > T.stringof, tail), file, line);
> > 
> >      }
> > 
> > }
> > 
> > - Jonathan M Davis
> :
> :-) That's not was I was looking for, IIUC. (And explains the mystery about
> 
> passing a statement around). Seems one cannot write
> 	assertThrown (1/0, ZeroDivisionError);
> or
> 	assertThrown (divide(1,0), ZeroDivisinoError);
> or can we? If I was looking for a variant of assert able to deal with
> throwing statements. (Check they throw, precisely). Obvious use case:
> 
> unittest {
>      assert(divide(2,1) == 2);
>      assert(divide(1,1) == 1);
>      assert(throws(divide(1,0), ZeroDivisionError));
> }

assertThrown!ZeroDivisionError(divide(1, 0));

should work as long as divide throws a ZeroDivisionError when given a 0 as its 
second parameter. If it does throw such an exception, then nothing happens - 
just like with assert. If no ZeroDivisionError is thrown, then an AssertError is 
thrown - just like with assert. However, with normal 1/0, I'm pretty sure that 
that just segfaults.

> But my dream unittest tool looks like check(statement, outcome):
> 
> unittest {
>      check(divide(2,1), 2);
>      check(divide(1,1), 1);
>      check(divide(1,0), ZeroDivisionError);
>      check(divide(3,1), 2);
> }
> 
> On verbose, would output:
>      divide(2,1) --> 2
>      divide(1,1) --> 1
>      divide(0,1) --> ZeroDivisionError
> ******* unittest check error *************
>      statement  : divide(3,1)
>      expected   : 2
>      outcome    : 3
> ******************************************
> 
> On silent, would output only the error.

assert does nothing on success and throws an AssertError on failure, so that's 
exactly what all of the functions that I've written for std.unittests (which 
will likely going in std.exception rather than being their own module) do. I'm 
not writing any functions which change how unit tests work in D. I'm just 
augmenting assert.

And honestly, I'd consider all that output that you have there really noisy and 
useless. What does it matter what happens on success? It's failure that you need 
to worry about. I can understand the folks who want unittest blocks to print 
that they've been run so that you can see the progress of the tests, but I see 
_zero_ value in printing out that an assertion succeeded.

Regardless, the way unit tests work in D is that they print nothing on success 
and throw AssertError on failure (and therefore given you the file and line 
number of the failure along with its message (if any) and stacktrace). So, 
that's what assertThrown does.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list