Thread: [Perlunit-users] Expected exceptions?
Status: Beta
Brought to you by:
mca1001
From: stefan k. <ste...@fu...> - 2007-05-01 09:45:30
|
Hi All, is there any simple way of achieving this: sub test_foo { my $self = shift; my $obj_to_test = ObjToTest->new('yadda', 1); # 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'); } In other words - I want to check that a specific object method dies with a specific message. There are examples included using ExceptionChecker.pm and WillDie.pm, but I can't seem to achieve the above. Thanks in advance for any pointers stefan -- Stefan Kruger Future Publishing Limited (registered company number 2008885) is a wholly owned subsidiary of Future plc (registered company number 3757874), both of which are incorporated in England and Wales and share the same registered address at Beauford Court, 30 Monmouth Street, Bath BA1 2BW. This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to which they are addressed. If you have received this email in error please reply to this email and then delete it. Please note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of Future. The recipient should check this email and any attachments for the presence of viruses. Future accepts no liability for any damage caused by any virus transmitted by this email. Future may regularly and randomly monitor outgoing and incoming emails and other telecommunications on its email and telecommunications systems. By replying to this email you give your consent to such monitoring. ***** Save resources: think before you print. |
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"); }); } |