4 package Test::Exception;
6 use Sub::Uplevel qw( uplevel );
7 use base qw( Exporter );
10 our $VERSION = '0.27';
11 our @EXPORT = qw(dies_ok lives_ok throws_ok lives_and);
13 my $Tester = Test::Builder->new;
19 $Tester->exported_to( $package );
22 $self->export_to_level( 1, $self, $_ ) foreach @EXPORT;
27 Test::Exception - Test exception based code
31 use Test::More tests => 5;
34 # or if you don't need Test::More
36 use Test::Exception tests => 5;
40 # Check that the stringified exception matches given regex
41 throws_ok { $foo->method } qr/division by zero/, 'zero caught okay';
43 # Check an exception of the given class (or subclass) is thrown
44 throws_ok { $foo->method } 'Error::Simple', 'simple error thrown';
46 # all Test::Exceptions subroutines are guaranteed to preserve the state
47 # of $@ so you can do things like this after throws_ok and dies_ok
48 like $@, 'what the stringified exception should look like';
50 # Check that something died - we do not care why
51 dies_ok { $foo->method } 'expecting to die';
53 # Check that something did not die
54 lives_ok { $foo->method } 'expecting to live';
56 # Check that a test runs without an exception
57 lives_and { is $foo->method, 42 } 'method is 42';
59 # or if you don't like prototyped functions
61 throws_ok( sub { $foo->method }, qr/division by zero/,
63 throws_ok( sub { $foo->method }, 'Error::Simple',
64 'simple error thrown' );
65 dies_ok( sub { $foo->method }, 'expecting to die' );
66 lives_ok( sub { $foo->method }, 'expecting to live' );
67 lives_and( sub { is $foo->method, 42 }, 'method is 42' );
72 This module provides a few convenience methods for testing exception based code. It is built with
73 L<Test::Builder> and plays happily with L<Test::More> and friends.
75 If you are not already familiar with L<Test::More> now would be the time to go take a look.
77 You can specify the test plan when you C<use Test::Exception> in the same way as C<use Test::More>.
78 See L<Test::More> for details.
80 NOTE: Test::Exception only checks for exceptions. It will ignore other methods of stopping
81 program execution - including exit(). If you have an exit() in evalled code Test::Exception
82 will not catch this with any of its testing functions.
86 sub _quiet_caller (;$) { ## no critic Prototypes
89 if( wantarray and !@_ ) {
90 return (CORE::caller($height))[0..2];
93 return CORE::caller($height);
100 # local works here because Sub::Uplevel has already overridden caller
101 local *CORE::GLOBAL::caller;
102 { no warnings 'redefine'; *CORE::GLOBAL::caller = \&_quiet_caller; }
104 eval { uplevel 3, $coderef };
110 my $exception = shift;
111 return ref $exception || $exception ne '';
115 sub _exception_as_string {
116 my ( $prefix, $exception ) = @_;
117 return "$prefix normal exit" unless _is_exception( $exception );
118 my $class = ref $exception;
119 $exception = "$class ($exception)"
120 if $class && "$exception" !~ m/^\Q$class/;
122 return "$prefix $exception";
130 Tests to see that a specific exception is thrown. throws_ok() has two forms:
132 throws_ok BLOCK REGEX, TEST_DESCRIPTION
133 throws_ok BLOCK CLASS, TEST_DESCRIPTION
135 In the first form the test passes if the stringified exception matches the give regular expression. For example:
137 throws_ok { read_file( 'unreadable' ) } qr/No file/, 'no file';
139 If your perl does not support C<qr//> you can also pass a regex-like string, for example:
141 throws_ok { read_file( 'unreadable' ) } '/No file/', 'no file';
143 The second form of throws_ok() test passes if the exception is of the same class as the one supplied, or a subclass of that class. For example:
145 throws_ok { $foo->bar } "Error::Simple", 'simple error';
147 Will only pass if the C<bar> method throws an Error::Simple exception, or a subclass of an Error::Simple exception.
149 You can get the same effect by passing an instance of the exception you want to look for. The following is equivalent to the previous example:
151 my $SIMPLE = Error::Simple->new;
152 throws_ok { $foo->bar } $SIMPLE, 'simple error';
154 Should a throws_ok() test fail it produces appropriate diagnostic messages. For example:
156 not ok 3 - simple error
157 # Failed test (test.t at line 48)
158 # expecting: Error::Simple exception
161 Like all other Test::Exception functions you can avoid prototypes by passing a subroutine explicitly:
163 throws_ok( sub {$foo->bar}, "Error::Simple", 'simple error' );
165 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
167 A description of the exception being checked is used if no optional test description is passed.
172 sub throws_ok (&$;$) {
173 my ( $coderef, $expecting, $description ) = @_;
174 croak "throws_ok: must pass exception class/object or regex"
175 unless defined $expecting;
176 $description = _exception_as_string( "threw", $expecting )
177 unless defined $description;
178 my $exception = _try_as_caller( $coderef );
179 my $regex = $Tester->maybe_regex( $expecting );
181 ? ( $exception =~ m/$regex/ )
183 $exception->isa( ref $expecting ? ref $expecting : $expecting )
185 $Tester->ok( $ok, $description );
187 $Tester->diag( _exception_as_string( "expecting:", $expecting ) );
188 $Tester->diag( _exception_as_string( "found:", $exception ) );
197 Checks that a piece of code dies, rather than returning normally. For example:
204 dies_ok { div( 1, 0 ) } 'divide by zero detected';
206 # or if you don't like prototypes
207 dies_ok( sub { div( 1, 0 ) }, 'divide by zero detected' );
209 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
211 Remember: This test will pass if the code dies for any reason. If you care about the reason it might be more sensible to write a more specific test using throws_ok().
213 The test description is optional, but recommended.
218 my ( $coderef, $description ) = @_;
219 my $exception = _try_as_caller( $coderef );
220 my $ok = $Tester->ok( _is_exception($exception), $description );
228 Checks that a piece of code doesn't die. This allows your test script to continue, rather than aborting if you get an unexpected exception. For example:
233 open my $fh, '<', $file or die "open failed ($!)\n";
239 lives_ok { $file = read_file('test.txt') } 'file read';
241 # or if you don't like prototypes
242 lives_ok( sub { $file = read_file('test.txt') }, 'file read' );
244 Should a lives_ok() test fail it produces appropriate diagnostic messages. For example:
247 # Failed test (test.t at line 15)
248 # died: open failed (No such file or directory)
250 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
252 The test description is optional, but recommended.
257 my ( $coderef, $description ) = @_;
258 my $exception = _try_as_caller( $coderef );
259 my $ok = $Tester->ok( ! _is_exception( $exception ), $description );
260 $Tester->diag( _exception_as_string( "died:", $exception ) ) unless $ok;
268 Run a test that may throw an exception. For example, instead of doing:
271 lives_ok { $file = read_file('answer.txt') } 'read_file worked';
272 is $file, "42", 'answer was 42';
274 You can use lives_and() like this:
276 lives_and { is read_file('answer.txt'), "42" } 'answer is 42';
277 # or if you don't like prototypes
278 lives_and(sub {is read_file('answer.txt'), "42"}, 'answer is 42');
280 Which is the same as doing
282 is read_file('answer.txt'), "42\n", 'answer is 42';
284 unless C<read_file('answer.txt')> dies, in which case you get the same kind of error as lives_ok()
286 not ok 1 - answer is 42
287 # Failed test (test.t at line 15)
288 # died: open failed (No such file or directory)
290 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
292 The test description is optional, but recommended.
296 sub lives_and (&;$) {
297 my ( $test, $description ) = @_;
299 local $Test::Builder::Level = $Test::Builder::Level + 1;
300 my $ok = \&Test::Builder::ok;
302 local *Test::Builder::ok = sub {
303 $_[2] = $description unless defined $_[2];
307 eval { $test->() } and return 1;
310 if ( _is_exception( $exception ) ) {
311 $Tester->ok( 0, $description );
312 $Tester->diag( _exception_as_string( "died:", $exception ) );
321 =head1 SKIPPING TEST::EXCEPTION TESTS
323 Sometimes we want to use Test::Exception tests in a test suite, but don't want to force the user to have Test::Exception installed. One way to do this is to skip the tests if Test::Exception is absent. You can do this with code something like this:
330 eval "use Test::Exception";
331 plan skip_all => "Test::Exception needed" if $@;
335 # ... tests that need Test::Exception ...
337 Note that we load Test::Exception in a C<BEGIN> block ensuring that the subroutine prototypes are in place before the rest of the test script is compiled.
342 There are some edge cases in Perl's exception handling where Test::Exception will miss exceptions
343 thrown in DESTROY blocks. See the RT bug L<http://rt.cpan.org/Ticket/Display.html?id=24678> for
344 details, along with the t/edge-cases.t in the distribution test suite. These will be addressed in
345 a future Test::Exception release.
347 If you find any more bugs please let me know by e-mail, or report the problem with
348 L<http://rt.cpan.org/>.
357 If you are interested in testing using Perl I recommend you visit L<http://qa.perl.org/> and join the excellent perl-qa mailing list. See L<http://lists.perl.org/showlist.cgi?name=perl-qa> for details on how to subscribe.
361 You can find users of Test::Exception, including the module author, on L<http://www.perlmonks.org/>. Feel free to ask questions on Test::Exception there.
365 The CPAN Forum is a web forum for discussing Perl's CPAN modules. The Test::Exception forum can be found at L<http://www.cpanforum.com/dist/Test-Exception>.
369 AnnoCPAN is a web site that allows community annotations of Perl module documentation. The Test::Exception annotations can be found at L<http://annocpan.org/~ADIE/Test-Exception/>.
376 If you think this module should do something that it doesn't (or does something that it shouldn't) please let me know.
378 You can see my current to do list at L<http://adrianh.tadalist.com/lists/public/15421>, with an RSS feed of changes at L<http://adrianh.tadalist.com/lists/feed_public/15421>.
381 =head1 ACKNOWLEDGMENTS
383 Thanks to chromatic and Michael G Schwern for the excellent Test::Builder, without which this module wouldn't be possible.
413 and various anonymous folk for comments, suggestions, bug reports and patches.
418 Adrian Howard <adrianh@quietstars.com>
420 If you can spare the time, please drop me a line if you find this module useful.
427 =item L<http://del.icio.us/tag/Test::Exception>
429 Delicious links on Test::Exception.
431 =item L<Test::Warn> & L<Test::NoWarnings>
433 Modules to help test warnings.
435 =item L<Test::Builder>
437 Support module for building test libraries.
439 =item L<Test::Simple> & L<Test::More>
441 Basic utilities for writing tests.
443 =item L<http://qa.perl.org/test-modules.html>
445 Overview of some of the many testing modules available on CPAN.
447 =item L<http://del.icio.us/tag/perl+testing>
449 Delicious links on perl testing.
456 Copyright 2002-2007 Adrian Howard, All Rights Reserved.
458 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.