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");
});
}
|