tag fourth (and hopefully last) alpha
[bioperl-live.git] / branch-1-6 / t / lib / Test / Exception.pm
blob0db23b761d162ebed1021a72e4e9904361df34da
1 use strict;
2 use warnings;
4 package Test::Exception;
5 use Test::Builder;
6 use Sub::Uplevel qw( uplevel );
7 use base qw( Exporter );
8 use Carp;
10 our $VERSION = '0.25';
11 our @EXPORT = qw(dies_ok lives_ok throws_ok lives_and);
13 my $Tester = Test::Builder->new;
15 sub import {
16 my $self = shift;
17 if ( @_ ) {
18 my $package = caller;
19 $Tester->exported_to( $package );
20 $Tester->plan( @_ );
22 $self->export_to_level( 1, $self, $_ ) foreach @EXPORT;
25 =head1 NAME
27 Test::Exception - Test exception based code
29 =head1 SYNOPSIS
31 use Test::More tests => 5;
32 use Test::Exception;
34 # or if you don't need Test::More
36 use Test::Exception tests => 5;
38 # then...
40 # Check that something died
41 dies_ok { $foo->method1 } 'expecting to die';
43 # Check that something did not die
44 lives_ok { $foo->method2 } 'expecting to live';
46 # Check that the stringified exception matches given regex
47 throws_ok { $foo->method3 } qr/division by zero/, 'zero caught okay';
49 # Check an exception of the given class (or subclass) is thrown
50 throws_ok { $foo->method4 } 'Error::Simple', 'simple error thrown';
52 # all Test::Exceptions subroutines are guaranteed to preserve the state
53 # of $@ so you can do things like this after throws_ok and dies_ok
54 like $@, 'what the stringified exception should look like';
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 dies_ok( sub { $foo->method1 }, 'expecting to die' );
62 lives_ok( sub { $foo->method2 }, 'expecting to live' );
63 throws_ok( sub { $foo->method3 }, qr/division by zero/,
64 'zero caught okay' );
65 throws_ok( sub { $foo->method4 }, 'Error::Simple',
66 'simple error thrown' );
67 lives_and( sub { is $foo->method, 42 }, 'method is 42' );
70 =head1 DESCRIPTION
72 This module provides a few convenience methods for testing exception based code. It is built with L<Test::Builder> and plays happily with L<Test::More> and friends.
74 If you are not already familiar with L<Test::More> now would be the time to go take a look.
76 You can specify the test plan when you C<use Test::Exception> in the same way as C<use Test::More>. See L<Test::More> for details.
78 =cut
81 sub _try_as_caller {
82 my $coderef = shift;
83 eval { uplevel 3, $coderef };
84 return $@;
88 sub _is_exception {
89 my $exception = shift;
90 return ref $exception || $exception ne '';
94 sub _exception_as_string {
95 my ( $prefix, $exception ) = @_;
96 return "$prefix normal exit" unless _is_exception( $exception );
97 my $class = ref $exception;
98 $exception = "$class ($exception)"
99 if $class && "$exception" !~ m/^\Q$class/;
100 chomp $exception;
101 return "$prefix $exception";
105 =over 4
107 =item B<dies_ok>
109 Checks that a piece of code dies, rather than returning normally. For example:
111 sub div {
112 my ( $a, $b ) = @_;
113 return $a / $b;
116 dies_ok { div( 1, 0 ) } 'divide by zero detected';
118 # or if you don't like prototypes
119 dies_ok( sub { div( 1, 0 ) }, 'divide by zero detected' );
121 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
123 The test description is optional, but recommended.
125 =cut
128 sub dies_ok (&;$) {
129 my ( $coderef, $description ) = @_;
130 my $exception = _try_as_caller( $coderef );
131 my $ok = $Tester->ok( _is_exception($exception), $description );
132 $@ = $exception;
133 return $ok;
137 =item B<lives_ok>
139 Checks that a piece of code exits normally, and doesn't die. For example:
141 sub read_file {
142 my $file = shift;
143 local $/;
144 open my $fh, '<', $file or die "open failed ($!)\n";
145 $file = <FILE>;
146 return $file;
149 my $file;
150 lives_ok { $file = read_file('test.txt') } 'file read';
152 # or if you don't like prototypes
153 lives_ok( sub { $file = read_file('test.txt') }, 'file read' );
155 Should a lives_ok() test fail it produces appropriate diagnostic messages. For example:
157 not ok 1 - file read
158 # Failed test (test.t at line 15)
159 # died: open failed (No such file or directory)
161 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
163 The test description is optional, but recommended.
165 =cut
167 sub lives_ok (&;$) {
168 my ( $coderef, $description ) = @_;
169 my $exception = _try_as_caller( $coderef );
170 my $ok = $Tester->ok( ! _is_exception( $exception ), $description );
171 $Tester->diag( _exception_as_string( "died:", $exception ) ) unless $ok;
172 $@ = $exception;
173 return $ok;
177 =item B<throws_ok>
179 Tests to see that a specific exception is thrown. throws_ok() has two forms:
181 throws_ok BLOCK REGEX, TEST_DESCRIPTION
182 throws_ok BLOCK CLASS, TEST_DESCRIPTION
184 In the first form the test passes if the stringified exception matches the give regular expression. For example:
186 throws_ok { read_file( 'unreadable' ) } qr/No file/, 'no file';
188 If your perl does not support C<qr//> you can also pass a regex-like string, for example:
190 throws_ok { read_file( 'unreadable' ) } '/No file/', 'no file';
192 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:
194 throws_ok { $foo->bar } "Error::Simple", 'simple error';
196 Will only pass if the C<bar> method throws an Error::Simple exception, or a subclass of an Error::Simple exception.
198 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:
200 my $SIMPLE = Error::Simple->new;
201 throws_ok { $foo->bar } $SIMPLE, 'simple error';
203 Should a throws_ok() test fail it produces appropriate diagnostic messages. For example:
205 not ok 3 - simple error
206 # Failed test (test.t at line 48)
207 # expecting: Error::Simple exception
208 # found: normal exit
210 Like all other Test::Exception functions you can avoid prototypes by passing a subroutine explicitly:
212 throws_ok( sub {$foo->bar}, "Error::Simple", 'simple error' );
214 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
216 A description of the exception being checked is used if no optional test description is passed.
218 =cut
221 sub throws_ok (&$;$) {
222 my ( $coderef, $expecting, $description ) = @_;
223 croak "throws_ok: must pass exception class/object or regex"
224 unless defined $expecting;
225 $description = _exception_as_string( "threw", $expecting )
226 unless defined $description;
227 my $exception = _try_as_caller( $coderef );
228 my $regex = $Tester->maybe_regex( $expecting );
229 my $ok = $regex
230 ? ( $exception =~ m/$regex/ )
231 : eval {
232 $exception->isa( ref $expecting ? ref $expecting : $expecting )
234 $Tester->ok( $ok, $description );
235 unless ( $ok ) {
236 $Tester->diag( _exception_as_string( "expecting:", $expecting ) );
237 $Tester->diag( _exception_as_string( "found:", $exception ) );
239 $@ = $exception;
240 return $ok;
244 =item B<lives_and>
246 Run a test that may throw an exception. For example, instead of doing:
248 my $file;
249 lives_ok { $file = read_file('answer.txt') } 'read_file worked';
250 is $file, "42", 'answer was 42';
252 You can use lives_and() like this:
254 lives_and { is read_file('answer.txt'), "42" } 'answer is 42';
255 # or if you don't like prototypes
256 lives_and(sub {is read_file('answer.txt'), "42"}, 'answer is 42');
258 Which is the same as doing
260 is read_file('answer.txt'), "42\n", 'answer is 42';
262 unless C<read_file('answer.txt')> dies, in which case you get the same kind of error as lives_ok()
264 not ok 1 - answer is 42
265 # Failed test (test.t at line 15)
266 # died: open failed (No such file or directory)
268 A true value is returned if the test succeeds, false otherwise. On exit $@ is guaranteed to be the cause of death (if any).
270 The test description is optional, but recommended.
272 =cut
274 sub lives_and (&;$) {
275 my ( $test, $description ) = @_;
277 local $Test::Builder::Level = $Test::Builder::Level + 1;
278 my $ok = \&Test::Builder::ok;
279 no warnings;
280 local *Test::Builder::ok = sub {
281 $_[2] = $description unless defined $_[2];
282 $ok->(@_);
284 use warnings;
285 eval { $test->() } and return 1;
287 my $exception = $@;
288 if ( _is_exception( $exception ) ) {
289 $Tester->ok( 0, $description );
290 $Tester->diag( _exception_as_string( "died:", $exception ) );
292 $@ = $exception;
293 return;
296 =back
299 =head1 SKIPPING TEST::EXCEPTION TESTS
301 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:
303 use strict;
304 use warnings;
305 use Test::More;
307 BEGIN {
308 eval "use Test::Exception";
309 plan skip_all => "Test::Exception needed" if $@;
312 plan tests => 2;
313 # ... tests that need Test::Exception ...
315 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.
318 =head1 BUGS
320 None known at the time of writing.
322 If you find any please let me know by e-mail, or report the problem with L<http://rt.cpan.org/>.
325 =head1 COMMUNITY
327 =over 4
329 =item perl-qa
331 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.
333 =item perlmonks
335 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.
337 =item CPAN::Forum
339 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>.
341 =item AnnoCPAN
343 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/>.
345 =back
348 =head1 TO DO
350 If you think this module should do something that it doesn't (or does something that it shouldn't) please let me know.
352 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>.
355 =head1 ACKNOWLEDGMENTS
357 Thanks to chromatic and Michael G Schwern for the excellent Test::Builder, without which this module wouldn't be possible.
359 Thanks to
360 Adam Kennedy,
361 Andy Lester,
362 Aristotle,
363 Ben Prew,
364 Cees Hek,
365 chromatic,
366 Curt Sampson,
367 David Cantrell,
368 David Golden,
369 David Wheeler,
370 Janek Schleicher,
371 Jim Keenan,
372 Jos I. Boumans,
373 Jost Krieger,
374 Mark Fowler,
375 Michael G Schwern,
376 Paul McCann,
377 Perrin Harkins,
378 Peter Scott,
379 Rob Muhlestein
380 Scott R. Godin,
381 Steve Purkis,
382 Steve,
383 Tim Bunce,
384 and various anonymous folk for comments, suggestions, bug reports and patches.
387 =head1 AUTHOR
389 Adrian Howard <adrianh@quietstars.com>
391 If you can spare the time, please drop me a line if you find this module useful.
394 =head1 SEE ALSO
396 =over 4
398 =item L<Test::Builder>
400 Support module for building test libraries.
402 =item L<Test::Simple> & L<Test::More>
404 Basic utilities for writing tests.
406 =item L<Test::Warn> & L<Test::NoWarnings>
408 Modules to help test warnings.
410 =item L<http://qa.perl.org/test-modules.html>
412 Overview of some of the many testing modules available on CPAN.
414 =item L<http://del.icio.us/tag/Test::Exception>
416 Delicious links on Test::Exception.
418 =item L<http://del.icio.us/tag/perl+testing>
420 Delicious links on perl testing.
422 =back
425 =head1 LICENCE
427 Copyright 2002-2007 Adrian Howard, All Rights Reserved.
429 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
431 =cut