File Coverage

blib/lib/Test/Aggregate/Nested.pm
Criterion Covered Total %
statement 75 79 94.9
branch 24 28 85.7
condition 2 2 100.0
subroutine 14 15 93.3
pod 0 3 0.0
total 115 127 90.5


line stmt bran cond sub pod time code
1             package Test::Aggregate::Nested;
2              
3 8     8   30333 use strict;
  8         16  
  8         225  
4 8     8   41 use warnings;
  8         13  
  8         248  
5              
6 8     8   1791 use Test::More;
  8         34986  
  8         68  
7 8     8   3819 use Test::Aggregate::Base;
  8         17  
  8         78  
8 8     8   722 use Carp;
  8         14  
  8         598  
9 8     8   3432 use FindBin;
  8         4952  
  8         331  
10              
11 8     8   38 use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
  8         12  
  8         2902  
12             @ISA = 'Test::Aggregate::Base';
13              
14             =encoding utf-8
15              
16             =head1 NAME
17              
18             Test::Aggregate::Nested - Aggregate C<*.t> tests to make them run faster.
19              
20             =head1 VERSION
21              
22             Version 0.373
23              
24             =cut
25              
26             our $VERSION = '0.373';
27             $VERSION = eval $VERSION;
28              
29             =head1 SYNOPSIS
30              
31             use Test::Aggregate::Nested;
32              
33             my $tests = Test::Aggregate::Nested->new( {
34             dirs => $aggregate_test_dir,
35             verbose => 1,
36             } );
37             $tests->run;
38              
39             =head1 DESCRIPTION
40              
41             B<ALPHA WARNING>: this is alpha code. Conceptually it is superior to
42             C<Test::Aggregate>, but in reality, it might not be. We'll see.
43              
44             This module is almost identical to C<Test::Aggregate> and will in the future
45             be the preferred way of aggregating tests (until someone comes up with
46             something better :)
47              
48             C<Test::Aggregate::Nested> requires a 0.8901 or better of C<Test::More>. This
49             is because we use its C<subtest> function. Currently we C<croak> if this
50             function is not available.
51              
52             Because the TAP output is nested, you'll find it much easier to see which
53             tests result in which output. For example, consider the following snippet of
54             TAP.
55              
56             1..2
57             1..5
58             ok 1 - aggtests/check_plan.t ***** 1
59             ok 2 - aggtests/check_plan.t ***** 2
60             ok 3 # skip checking plan (aggtests/check_plan.t ***** 3)
61             ok 4 - env variables should not hang around
62             ok 5 - aggtests/check_plan.t ***** 4
63             ok 1 - Tests for aggtests/check_plan.t
64             1..1
65             ok 1 - subs work!
66             ok 2 - Tests for aggtests/subs.t
67              
68             At the end of each nested test is a summary test line explaining which program
69             we ran tests for.
70              
71             C<Test::Aggregate::Nested> asserts a plan equal to the number of test files
72             aggregated, something which C<Test::Aggregate> could not do. Because of this,
73             we no longer export C<Test::More> functions. If you need additional tests
74             before or after aggregation, you can run the aggregated tests in a subtest:
75              
76             use Test::More tests => 2;
77             use Test::Aggregate::Nested;
78              
79             subtest 'Nested tests' => sub {
80             Test::Aggregate::Nested->new({ dirs => 'aggtests/' })->run;
81             };
82             ok $some_other_test;
83              
84             or disable the generation of the plan with the parameter C<no_generate_plan>:
85              
86             use Test::More;
87             use Test::Aggregate::Nested;
88              
89             Test::Aggregate::Nested->new({ dirs => 'aggtests/', no_generate_plan => 1 })->run;
90             ok $some_other_test;
91             done_testing();
92              
93             =head1 CAVEATS
94              
95             C<Test::Aggregate::Nested> is much cleaner than C<Test::Aggregate>, so I don't
96             support the C<dump> argument. If this is needed, let me know and I'll see
97             about fixing this.
98              
99             The "variable will not stay shared" warnings from C<Test::Aggregate> (see its
100             CAVEATS section) are no longer applicable.
101              
102             =cut
103              
104             my $REINIT_FINDBIN = FindBin->can(q/again/) || sub {};
105              
106             sub new {
107 9     9 0 3838 my ( $class, $arg_for ) = @_;
108 9 50       36 if ( $arg_for->{dump} ) {
109 0         0 require Carp;
110 0         0 carp("Dump files are not supported under Test::Aggregate::Nested.");
111             }
112 9 50       57 unless ( Test::More->can('subtest') ) {
113 0         0 my $tm_version = Test::More->VERSION;
114 0         0 croak(<<" END");
115             Test::More version $tm_version does not support nested TAP.
116             Please upgrade to version 0.8901 or newer to use Test::Aggregate::Nested.
117             END
118             }
119 9         103 $class->SUPER::new($arg_for);
120             }
121              
122             sub run {
123 9     9 0 1770 my $self = shift;
124              
125 9         36 local $Test::Aggregate::Base::_pid = $$;
126              
127 9         19 my %test_phase;
128 9         45 foreach my $attr ( $self->_code_attributes ) {
129 36         68 my $method = "_$attr";
130 36   100 68   210 $test_phase{$attr} = $self->$method || sub { };
131             }
132              
133 9         69 my @tests = $self->_get_tests;
134              
135 9         45 my ( $current, $total ) = ( 0, scalar @tests );
136 9 100       47 if (! $self->{no_generate_plan}) {
137 8         34 plan tests => $total;
138             }
139 9         960 $test_phase{startup}->();
140 9         27 for my $test (@tests) {
141 39         403 $current++;
142 8     8   39 no warnings 'uninitialized';
  8         18  
  8         870  
143 39         1522 local %ENV = %ENV;
144 39         286 local $/ = $/;
145 39         356 local @INC = @INC;
146 39         66 local $_ = $_;
147 39         112 local $| = $|;
148 39         10888 local %SIG = %SIG;
149 39         453 local $@;
150 8     8   41 use warnings 'uninitialized';
  8         21  
  8         3679  
151              
152             # restrict this scope as much as possible
153 39         402 local $0 = $test;
154 39         131 $test_phase{setup}->($test);
155 39 100       298 $REINIT_FINDBIN->() if $self->_findbin;
156 39         9566 my $package = $self->_get_package($test);
157 39 100       159 if ( $self->_verbose ) {
158 28         144 Test::More::diag("Running tests for $test ($current out of $total)");
159             }
160 39         6972 eval <<" END";
161             package $package;
162             Test::Aggregate::Nested::_do_file_as_subtest(\$test);
163             END
164 38 50       22947 diag $@ if $@;
165 38         181 $test_phase{teardown}->($test);
166             }
167 8         81 $test_phase{shutdown}->();
168             }
169              
170       0 0   sub run_this_test_program { }
171              
172             sub _do_file_as_subtest {
173 39     39   67 my ($test) = @_;
174             subtest("Tests for $test", sub {
175 39     39   20265 my $error;
176             my $diag;
177              
178             {
179 39         52 local ($@, $!);
  39         184  
180             # if do("file") fails it will return undef (and set $@ or $!)
181 39 100       15890 unless(defined( my $return = do $test )){
182             # If there was an error be sure to propogate it.
183             # This isn't quite the same as what's described by `perldoc -f do`
184             # because there are no rules about what a .t file should return.
185             # If the file doesn't return a defined value there's no way to
186             # tell the difference between a test that errored and one that
187             # returned undef but did something that happened to set `$!`
188             # (for example, a file that skips when it looks for a file that
189             # isn't found), so we shouldn't treat it as an error.
190             # If the file fails to read then subtest() will complain
191             # that no tests were run (and consider it a failure).
192             # That should be sufficient.
193              
194 11         5253 my $ex_class = 'Test::Builder::Exception';
195 11 100       52 if( my $e = $@ ){
    100          
196             $error = "Couldn't parse '$test': $e"
197             unless (
198             # a skip in a subtest will be an object
199 7 100       180 ref($e) ? eval { $e->isa($ex_class) } :
  3 100       38  
200             # a skip in a BEGIN ("use Test::More skip_all => $message") gets stringified
201             $e =~ /^\Q${ex_class}=HASH(0x\E[[:xdigit:]]+\Q)BEGIN failed--compilation aborted\E/
202             );
203             }
204             # If tests have been run we can assume the file was read.
205             # If not, print a warning message.
206             # Either way Test::Builder will handle marking it as pass/fail.
207             elsif( scalar(Test::Builder->new->details) == 0 ){
208             # It might have been an error, or might not, so try to get
209             # the author to help us out.
210 3         36 $diag = <<TEST_DIAG;
211             #
212             # WARNING:
213             # It is unknown if '$test' actually finished.
214             # To remove this warning have the test script end with a defined value.
215             #
216             TEST_DIAG
217             # This *may* indicate a failure to read the file.
218 3 50       33 $diag .= <<TEST_DIAG if $!;
219             # The following error was set (\$!):
220             # $!
221             #
222             TEST_DIAG
223             }
224             }
225             }
226             # show the error but don't halt everything
227 38 100       3046679 Test::More::diag($diag) if $diag;
228 38 100       184 Test::More::ok(0, "Error running ($test): $error") if $error;
229 39         312 });
230             }
231              
232             1;
233              
234             __END__
235              
236             =head1 AUTHOR
237              
238             Curtis Poe, C<< <ovid at cpan.org> >>
239              
240             =head1 BUGS
241              
242             Please report any bugs or feature requests to
243             C<bug-test-aggregate at rt.cpan.org>, or through the web interface at
244             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Aggregate>.
245             I will be notified, and then you'll automatically be notified of progress on
246             your bug as I make changes.
247              
248             =head1 SUPPORT
249              
250             You can find documentation for this module with the perldoc command.
251              
252             perldoc Test::Aggregate::Nested
253              
254             You can also find information oneline:
255              
256             L<http://metacpan.org/release/Test-Aggregate>
257              
258             =head1 ACKNOWLEDGEMENTS
259              
260             Many thanks to mauzo (L<http://use.perl.org/~mauzo/> for helping me find the
261             'skip_all' bug.
262              
263             Thanks to Johan Lindström for pointing me to Apache::Registry.
264              
265             =head1 COPYRIGHT & LICENSE
266              
267             Copyright 2007 Curtis "Ovid" Poe, all rights reserved.
268              
269             This program is free software; you can redistribute it and/or modify it
270             under the same terms as Perl itself.
271              
272             =cut