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

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Perlunit-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/perlunit-users

Reply via email to