File Coverage

blib/lib/Test/Exception.pm
Criterion Covered Total %
statement 96 102 94.1
branch 30 36 83.3
condition 8 12 66.6
subroutine 18 18 100.0
pod 4 4 100.0
total 156 172 90.7


line stmt bran cond sub pod time code
1 10     10   265553 use strict;
  10         24  
  10         248  
2 10     10   51 use warnings;
  10         19  
  10         343  
3              
4             package Test::Exception;
5 10     10   1074 use Test::Builder;
  10         11168  
  10         231  
6 10     10   7093 use Sub::Uplevel qw( uplevel );
  10         10627  
  10         63  
7 10     10   439 use base qw( Exporter );
  10         20  
  10         3786  
8              
9             our $VERSION = '0.41';
10             our @EXPORT = qw(dies_ok lives_ok throws_ok lives_and);
11              
12             my $Tester = Test::Builder->new;
13              
14             sub import {
15 10     10   65 my $self = shift;
16 10 100       34 if ( @_ ) {
17 1         3 my $package = caller;
18 1         18 $Tester->exported_to( $package );
19 1         9 $Tester->plan( @_ );
20             };
21 10         4328 $self->export_to_level( 1, $self, $_ ) foreach @EXPORT;
22             }
23              
24             =head1 NAME
25              
26             Test::Exception - Test exception-based code
27              
28             =head1 SYNOPSIS
29              
30             use Test::More tests => 5;
31             use Test::Exception;
32              
33             # or if you don't need Test::More
34              
35             use Test::Exception tests => 5;
36              
37             # then...
38              
39             # Check that the stringified exception matches given regex
40             throws_ok { $foo->method } qr/division by zero/, 'zero caught okay';
41              
42             # Check an exception of the given class (or subclass) is thrown
43             throws_ok { $foo->method } 'Error::Simple', 'simple error thrown';
44            
45             # all Test::Exceptions subroutines are guaranteed to preserve the state
46             # of $@ so you can do things like this after throws_ok and dies_ok
47             like $@, 'what the stringified exception should look like';
48              
49             # Check that something died - we do not care why
50             dies_ok { $foo->method } 'expecting to die';
51              
52             # Check that something did not die
53             lives_ok { $foo->method } 'expecting to live';
54              
55             # Check that a test runs without an exception
56             lives_and { is $foo->method, 42 } 'method is 42';
57            
58             # or if you don't like prototyped functions
59            
60             throws_ok( sub { $foo->method }, qr/division by zero/,
61             'zero caught okay' );
62             throws_ok( sub { $foo->method }, 'Error::Simple',
63             'simple error thrown' );
64             dies_ok( sub { $foo->method }, 'expecting to die' );
65             lives_ok( sub { $foo->method }, 'expecting to live' );
66             lives_and( sub { is $foo->method, 42 }, 'method is 42' );
67              
68              
69             =head1 DESCRIPTION
70              
71             This module provides a few convenience methods for testing exception based code. It is built with
72             L<Test::Builder> and plays happily with L<Test::More> and friends.
73              
74             If you are not already familiar with L<Test::More> now would be the time to go take a look.
75              
76             You can specify the test plan when you C<use Test::Exception> in the same way as C<use Test::More>.
77             See L<Test::More> for details.
78              
79             NOTE: Test::Exception only checks for exceptions. It will ignore other methods of stopping
80             program execution - including exit(). If you have an exit() in evalled code Test::Exception
81             will not catch this with any of its testing functions.
82              
83             NOTE: This module uses L<Sub::Uplevel> and relies on overriding
84             C<CORE::GLOBAL::caller> to hide your test blocks from the call stack. If this
85             use of global overrides concerns you, the L<Test::Fatal> module offers a more
86             minimalist alternative.
87              
88             =cut
89              
90             sub _quiet_caller (;$) { ## no critic Prototypes
91 72     72   4013 my $height = $_[0];
92 72         89 $height++;
93              
94 72 100       162 if ( CORE::caller() eq 'DB' ) {
95             # passthrough the @DB::args trick
96             package DB;
97 21 50       64 if( wantarray ) {
98 21 50       53 if ( !@_ ) {
99 0         0 return (CORE::caller($height))[0..2];
100             }
101             else {
102             # If we got here, we are within a Test::Exception test, and
103             # something is producing a stacktrace. In case this is a full
104             # trace (i.e. confess() ), we have to make sure that the sub
105             # args are not visible. If we do not do this, and the test in
106             # question is throws_ok() with a regex, it will end up matching
107             # against itself in the args to throws_ok().
108             #
109             # While it is possible (and maybe wise), to test if we are
110             # indeed running under throws_ok (by crawling the stack right
111             # up from here), the old behavior of Test::Exception was to
112             # simply obliterate @DB::args altogether in _quiet_caller, so
113             # we are just preserving the behavior to avoid surprises
114             #
115 21         122 my @frame_info = CORE::caller($height);
116 21         38 @DB::args = ();
117 21         137 return @frame_info;
118             }
119             }
120              
121             # fallback if nothing above returns
122 0         0 return CORE::caller($height);
123             }
124             else {
125 51 50 33     264 if( wantarray and !@_ ) {
126 0         0 return (CORE::caller($height))[0..2];
127             }
128             else {
129 51         324 return CORE::caller($height);
130             }
131             }
132             }
133              
134             sub _try_as_caller {
135 33     33   72 my $coderef = shift;
136              
137             # local works here because Sub::Uplevel has already overridden caller
138 33         93 local *CORE::GLOBAL::caller;
139 10     10   60 { no warnings 'redefine'; *CORE::GLOBAL::caller = \&_quiet_caller; }
  10         20  
  10         8697  
  33         44  
  33         85  
140              
141 33         65 eval { uplevel 3, $coderef };
  33         93  
142 33         811 return $@;
143             };
144              
145              
146             sub _is_exception {
147 48     48   82 my $exception = shift;
148 48   100     303 return ref $exception || $exception ne '';
149             };
150              
151              
152             sub _exception_as_string {
153 34     34   67 my ( $prefix, $exception ) = @_;
154 34 100       72 return "$prefix normal exit" unless _is_exception( $exception );
155 32         78 my $class = ref $exception;
156 32 100 100     250 $exception = "$class ($exception)"
157             if $class && "$exception" !~ m/^\Q$class/;
158 32         162 chomp $exception;
159 32         132 return "$prefix $exception";
160             };
161              
162              
163             =over 4
164              
165             =item B<throws_ok>
166              
167             Tests to see that a specific exception is thrown. throws_ok() has two forms:
168              
169             throws_ok BLOCK REGEX, TEST_DESCRIPTION
170             throws_ok BLOCK CLASS, TEST_DESCRIPTION
171              
172             In the first form the test passes if the stringified exception matches the give regular expression. For example:
173              
174             throws_ok { read_file( 'unreadable' ) } qr/No file/, 'no file';
175              
176             If your perl does not support C<qr//> you can also pass a regex-like string, for example:
177              
178             throws_ok { read_file( 'unreadable' ) } '/No file/', 'no file';
179              
180             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:
181              
182             throws_ok { $foo->bar } "Error::Simple", 'simple error';
183              
184             Will only pass if the C<bar> method throws an Error::Simple exception, or a subclass of an Error::Simple exception.
185              
186             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:
187              
188             my $SIMPLE = Error::Simple->new;
189             throws_ok { $foo->bar } $SIMPLE, 'simple error';
190              
191             Should a throws_ok() test fail it produces appropriate diagnostic messages. For example:
192              
193             not ok 3 - simple error
194             # Failed test (test.t at line 48)
195             # expecting: Error::Simple exception
196             # found: normal exit
197              
198             Like all other Test::Exception functions you can avoid prototypes by passing a subroutine explicitly:
199              
200             throws_ok( sub {$foo->bar}, "Error::Simple", 'simple error' );
201              
202             A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
203              
204             A description of the exception being checked is used if no optional test description is passed.
205              
206             NOTE: Remember when you C<die $string_without_a_trailing_newline> perl will
207             automatically add the current script line number, input line number and a newline. This will
208             form part of the string that throws_ok regular expressions match against.
209              
210              
211             =cut
212              
213              
214             sub throws_ok (&$;$) {
215 22     22 1 14221 my ( $coderef, $expecting, $description ) = @_;
216 22 100       70 unless (defined $expecting) {
217 1         8 require Carp;
218 1         18 Carp::croak( "throws_ok: must pass exception class/object or regex" );
219             }
220 21 100       73 $description = _exception_as_string( "threw", $expecting )
221             unless defined $description;
222 21         55 my $exception = _try_as_caller( $coderef );
223 21         84 my $regex = $Tester->maybe_regex( $expecting );
224             my $ok = $regex
225             ? ( $exception =~ m/$regex/ )
226 21 100       460 : eval {
227 9 100       61 $exception->isa( ref $expecting ? ref $expecting : $expecting )
228             };
229 21         104 $Tester->ok( $ok, $description );
230 21 100       8858 unless ( $ok ) {
231 9         24 $Tester->diag( _exception_as_string( "expecting:", $expecting ) );
232 9         719 $Tester->diag( _exception_as_string( "found:", $exception ) );
233             };
234 21         736 $@ = $exception;
235 21         213 return $ok;
236             };
237              
238              
239             =item B<dies_ok>
240              
241             Checks that a piece of code dies, rather than returning normally. For example:
242              
243             sub div {
244             my ( $a, $b ) = @_;
245             return $a / $b;
246             };
247              
248             dies_ok { div( 1, 0 ) } 'divide by zero detected';
249              
250             # or if you don't like prototypes
251             dies_ok( sub { div( 1, 0 ) }, 'divide by zero detected' );
252              
253             A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
254              
255             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().
256              
257             The test description is optional, but recommended.
258              
259             =cut
260              
261             sub dies_ok (&;$) {
262 6     6 1 2475 my ( $coderef, $description ) = @_;
263 6         20 my $exception = _try_as_caller( $coderef );
264 6         21 my $ok = $Tester->ok( _is_exception($exception), $description );
265 6         2466 $@ = $exception;
266 6         16 return $ok;
267             }
268              
269              
270             =item B<lives_ok>
271              
272             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:
273              
274             sub read_file {
275             my $file = shift;
276             local $/;
277             open my $fh, '<', $file or die "open failed ($!)\n";
278             $file = <FILE>;
279             return $file;
280             };
281              
282             my $file;
283             lives_ok { $file = read_file('test.txt') } 'file read';
284              
285             # or if you don't like prototypes
286             lives_ok( sub { $file = read_file('test.txt') }, 'file read' );
287              
288             Should a lives_ok() test fail it produces appropriate diagnostic messages. For example:
289              
290             not ok 1 - file read
291             # Failed test (test.t at line 15)
292             # died: open failed (No such file or directory)
293              
294             A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
295              
296             The test description is optional, but recommended.
297              
298             =cut
299              
300             sub lives_ok (&;$) {
301 6     6 1 4388 my ( $coderef, $description ) = @_;
302 6         16 my $exception = _try_as_caller( $coderef );
303 6         18 my $ok = $Tester->ok( ! _is_exception( $exception ), $description );
304 6 100       2549 $Tester->diag( _exception_as_string( "died:", $exception ) ) unless $ok;
305 6         334 $@ = $exception;
306 6         19 return $ok;
307             }
308              
309              
310             =item B<lives_and>
311              
312             Run a test that may throw an exception. For example, instead of doing:
313              
314             my $file;
315             lives_ok { $file = read_file('answer.txt') } 'read_file worked';
316             is $file, "42", 'answer was 42';
317              
318             You can use lives_and() like this:
319              
320             lives_and { is read_file('answer.txt'), "42" } 'answer is 42';
321             # or if you don't like prototypes
322             lives_and(sub {is read_file('answer.txt'), "42"}, 'answer is 42');
323              
324             Which is the same as doing
325              
326             is read_file('answer.txt'), "42\n", 'answer is 42';
327              
328             unless C<read_file('answer.txt')> dies, in which case you get the same kind of error as lives_ok()
329              
330             not ok 1 - answer is 42
331             # Failed test (test.t at line 15)
332             # died: open failed (No such file or directory)
333              
334             A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
335              
336             The test description is optional, but recommended.
337              
338             =cut
339              
340             my $is_test2 = $INC{'Test2/Global.pm'} || $INC{'Test2/API.pm'} || $INC{'Test2/Context.pm'};
341             my $is_stream = $INC{'Test/Stream/Sync.pm'};
342             our $LIVES_AND_NAME;
343             if ($is_test2) {
344             Test2::Global::test2_stack()->top->filter(sub {
345             my ($hub, $e) = @_;
346             return $e unless defined $LIVES_AND_NAME;
347             return $e unless $e->isa('Test2::Event::Ok');
348             return $e if defined $e->name;
349             $e->set_name($LIVES_AND_NAME);
350             return $e;
351             });
352             }
353             elsif ($is_stream) {
354             Test::Stream::Sync->stack->top->munge(sub {
355             return unless defined $LIVES_AND_NAME;
356             my ($stream, $e) = @_;
357             return unless $e->isa('Test::Stream::Event::Ok');
358             return if defined $e->name;
359             $e->set_name($LIVES_AND_NAME);
360             });
361             }
362              
363             sub lives_and (&;$) {
364 4     4 1 840 my ( $test, $description ) = @_;
365 4 50 33     24 if ($is_test2 || $is_stream) {
366 0         0 local $LIVES_AND_NAME = $description;
367 0 0       0 eval { $test->() } and return 1;
  0         0  
368             }
369             else {
370 4         9 local $Test::Builder::Level = $Test::Builder::Level + 1;
371 4         7 my $ok = \&Test::Builder::ok;
372 10     10   54 no warnings;
  10         18  
  10         815  
373             local *Test::Builder::ok = sub {
374 3 100   3   52 $_[2] = $description unless defined $_[2];
375 3         11 $ok->(@_);
376 4         21 };
377 10     10   51 use warnings;
  10         15  
  10         1638  
378 4 100       8 eval { $test->() } and return 1;
  4         11  
379             };
380 2         776 my $exception = $@;
381 2 100       6 if ( _is_exception( $exception ) ) {
382 1         5 $Tester->ok( 0, $description );
383 1         610 $Tester->diag( _exception_as_string( "died:", $exception ) );
384             };
385 2         81 $@ = $exception;
386 2         5 return;
387             }
388              
389             =back
390              
391              
392             =head1 SKIPPING TEST::EXCEPTION TESTS
393              
394             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:
395              
396             use strict;
397             use warnings;
398             use Test::More;
399            
400             BEGIN {
401             eval "use Test::Exception";
402             plan skip_all => "Test::Exception needed" if $@;
403             }
404            
405             plan tests => 2;
406             # ... tests that need Test::Exception ...
407              
408             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.
409              
410              
411             =head1 BUGS
412              
413             There are some edge cases in Perl's exception handling where Test::Exception will miss exceptions
414             thrown in DESTROY blocks. See the RT bug L<http://rt.cpan.org/Ticket/Display.html?id=24678> for
415             details, along with the t/edge-cases.t in the distribution test suite. These will be addressed in
416             a future Test::Exception release.
417              
418             If you find any more bugs please let me know by e-mail, or report the problem with
419             L<http://rt.cpan.org/>.
420              
421              
422             =head1 COMMUNITY
423              
424             =over 4
425              
426             =item perl-qa
427              
428             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.
429              
430             =item perlmonks
431              
432             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.
433              
434             =item CPAN::Forum
435              
436             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>.
437              
438             =item AnnoCPAN
439              
440             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/>.
441              
442             =back
443              
444              
445             =head1 TO DO
446              
447             If you think this module should do something that it doesn't (or does something that it shouldn't) please let me know.
448              
449             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>.
450              
451              
452             =head1 ACKNOWLEDGMENTS
453              
454             Thanks to chromatic and Michael G Schwern for the excellent Test::Builder, without which this module wouldn't be possible.
455              
456             Thanks to
457             Adam Kennedy,
458             Andy Lester,
459             Aristotle Pagaltzis,
460             Ben Prew,
461             Cees Hek,
462             Chris Dolan,
463             chromatic,
464             Curt Sampson,
465             David Cantrell,
466             David Golden,
467             David Tulloh,
468             David Wheeler,
469             J. K. O'Brien,
470             Janek Schleicher,
471             Jim Keenan,
472             Jos I. Boumans,
473             Joshua ben Jore,
474             Jost Krieger,
475             Mark Fowler,
476             Michael G Schwern,
477             Nadim Khemir,
478             Paul McCann,
479             Perrin Harkins,
480             Peter Rabbitson,
481             Peter Scott,
482             Ricardo Signes,
483             Rob Muhlestein,
484             Scott R. Godin,
485             Steve Purkis,
486             Steve,
487             Tim Bunce,
488             and various anonymous folk for comments, suggestions, bug reports and patches.
489              
490             =head1 AUTHOR
491              
492             Adrian Howard <adrianh@quietstars.com>
493              
494             If you can spare the time, please drop me a line if you find this module useful.
495              
496              
497             =head1 SEE ALSO
498              
499             =over 4
500              
501             =item L<http://del.icio.us/tag/Test::Exception>
502              
503             Delicious links on Test::Exception.
504              
505             =item L<Test::Fatal>
506              
507             A slightly different interface to testing exceptions, without overriding C<CORE::caller>.
508              
509             =item L<Test::Warnings> & L<Test::Warn> & L<Test::NoWarnings>
510              
511             Modules to help test warnings.
512              
513             =item L<Test::Builder>
514              
515             Support module for building test libraries.
516              
517             =item L<Test::Simple> & L<Test::More>
518              
519             Basic utilities for writing tests.
520              
521             =item L<http://qa.perl.org/test-modules.html>
522              
523             Overview of some of the many testing modules available on CPAN.
524              
525             =item L<http://del.icio.us/tag/perl+testing>
526              
527             Delicious links on perl testing.
528              
529             =back
530              
531              
532             =head1 LICENCE
533              
534             Copyright 2002-2007 Adrian Howard, All Rights Reserved.
535              
536             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
537              
538             =cut
539              
540             1;