Re: [Perlunit-users] Expected exceptions?
Status: Beta
Brought to you by:
mca1001
From: Matthew A. <mc...@us...> - 2007-05-03 21:09:48
|
On Tue, May 01, 2007 at 10:45:22AM +0100, stefan kruger wrote: > is there any simple way of achieving this: [...] > # This is wrong in so many different ways, and only intended to convey what > # I'd like to do > $self->assert_dies($obj_to_test->some_method('bobba', 2), 'my_die_message'); Yes, I have a bolt-on assert method like this in my local T:U:TestCase subclass. This is something I really must tidy up and add to the project, but in the mean time the source is below - under the current Perl Artistic licence if such a thing applies to so little code. If you just have one test class you can stuff it in as an extra method; or you can make a subclass and use that for your test; or you could hack your local install because hopefully the next release will contain the same code anyway. > In other words - I want to check that a specific object method dies > with a specific message. It's a common thing to want! With the code below present, I would do $self->assert_dies(qr/my_dir_message/, sub { $obj_to_test->some_method('bobba', 2) }, "other helpful fail-text"); The second arg is an anonymous subroutine so die'ing (or not) doesn't happen until after the assert_dies method starts to run. > There are examples included using ExceptionChecker.pm and > WillDie.pm, but I can't seem to achieve the above. Thanks for reminding me, I had forgotten about these. Matthew #8-) -- =head2 assert_dies( qr/message regex/, @coderefs, $descr]) Run each piece of code. Assert that each one dies, and that the resulting error message matches the regex. Extra description C<$descr> is optional. =cut sub assert_dies { my ($self, $regex, @coderef) = @_; # Need to include caller in failure message, since the builtin # line number reporting is no help my @caller = caller(); my $caller = "caller at $caller[1] line $caller[2]"; if (@coderef > 1 && !ref($coderef[-1])) { # Last item isn't code, take it as an extra piece of message $caller .= ", ".pop(@coderef); } $self->fail("arg1 not Regexp from $caller") unless ref($regex) eq 'Regexp'; $self->fail("Bad args (no coderefs) from $caller") unless @coderef; $self->fail("Bad args (coderefs aren't) from $caller") if grep {ref($_) ne 'CODE'} @coderef; for (my $i=0; $i<@coderef; $i++) { eval { $coderef[$i]->(); }; my $err = $@; my $which = ""; $which = join "", "[", $i+1, " of ", scalar @coderef, "]" if @coderef > 1; $self->fail("Code$which did not die, $caller") unless $err; $self->assert_matches($regex, $err, "Code$which, $caller:\n Died with '$err'\n which didn't match $regex"); } } # The self-tests for this code are the thing that desperately needs # tidying up before the code escapes... sub McaTestCaseTest::test_assert_dies { my $self = shift; # Run our assertion so it should pass, check it ran my $flag = 0; $self->assert_dies(qr/dodo style/, sub { $flag = "captured"; die "dodo style"; }); $self->assert_str_equals("captured", $flag); ### Use the builtin Test::Unit::Assert to check the assertion fails: # doesn't die $self->assert_raises('Test::Unit::Failure', sub { $self->assert_dies( qr/wibble/, sub { return 1; }); }); # wrong args $self->assert_raises('Test::Unit::Failure', sub { $self->assert_dies( "foo", sub { return 1; }); }); $self->assert_raises('Test::Unit::Failure', sub { $self->assert_dies( qr/foo/, sub { return 1; }, "This is not code", "Could be a message?"); }); # multi coderef, second has wrong message $self->assert_raises('Test::Unit::Failure', sub { $self->assert_dies( qr/wibble/, sub { die "wibble" }, sub { die "spong" }); }); # multi coderef, third doesn't die $self->assert_raises('Test::Unit::Failure', sub { $self->assert_dies( qr/wibble/, sub { die "eek wibble bonk" }, sub { die "boo wibble spong" }, sub { return 1; }); }); # old bug check $self->assert_raises('Test::Unit::Failure', sub { $self->assert_dies( qr/caller/i, sub { die "some other thing" } ); }); # Check the error messages are useful # Working so far, so can use the method under test! $self->assert_dies( qr/Code\[2 of 2\]/, sub { $self->assert_dies( qr/butter/, sub { die "butterfingers" }, sub { die "aiee" }); }, sub { $self->assert_dies( qr/oops/, sub { die "oops" }, sub { return 1 }); }); $self->assert_dies( qr/vital/, sub { $self->assert_dies( qr/foo/, sub { die "unhelpful message" }, "vital piece of info"); }); } |