File Coverage

lib/Module/Build/TestReporter.pm
Criterion Covered Total %
statement 43 117 36.7
branch 1 22 4.5
condition 7 14 50.0
subroutine 12 19 63.1
pod 0 7 0.0
total 63 179 35.2


line stmt bran cond sub pod time code
1             package Module::Build::TestReporter;
2              
3 4     4   27157 use strict;
  4         8  
  4         168  
4 4     4   23 use warnings;
  4         7  
  4         173  
5              
6 4     4   24 use vars '$VERSION';
  4         5  
  4         245  
7              
8             $VERSION = '1.00';
9              
10 4     4   21 use base 'Module::Build';
  4         14  
  4         5221  
11 4     4   426965 use Scalar::Util 'reftype';
  4         9  
  4         390  
12 4     4   1677 use File::Spec::Functions qw( devnull catdir );
  4         1856  
  4         1299  
13              
14             # if these subs had real names, they'd confuse caller() in SUPER.pm
15             # making them anonymous and assigning to *__ANON__ fixes that
16             # this is the "You don't have all of MBTR's dependencies installed" constructor
17             sub fake_new
18             {
19             return sub
20             {
21 5     5   196766 local *__ANON__ = 'new';
22 5         32 my ($class, %args) = @_;
23              
24 5   100     75 my $requires = $args{build_requires} ||= {};
25 5   100     53 $requires->{'SUPER'} ||= '1.10';
26 5   50     46 $requires->{'IPC::Open3'} ||= '';
27 5   50     33 $requires->{'Class::Roles'} ||= '';
28 5   50     37 $requires->{'Test::Harness'} ||= '2.47';
29              
30 5         63 Module::Build->new( %args );
31 4     4 0 32 };
32             }
33              
34             # this is the "Everything looks good!" constructor
35             sub new
36             {
37             my ($class, %args) = @_;
38             my $report_file = delete $args{report_file} || 'test_failures.txt';
39             my $report_address = delete $args{report_address}|| '';
40             my $self = $class->SUPER( %args );
41            
42             $self->notes( report_file => $report_file );
43             $self->notes( report_address => $report_address ) if $report_address;
44              
45             return $self;
46             }
47              
48             BEGIN
49             {
50             eval
51 4     4   8 {
52 4         2469 require SUPER;
53 3         11206 require IPC::Open3;
54              
55 3         10031 require Test::Harness::Straps;
56 0         0 require Class::Roles;
57              
58 0         0 IPC::Open3->import();
59 0         0 Class::Roles->import(
60             role => [qw(
61             new ACTION_test find_test_files save_failure_details
62             report_failures write_report
63             )]
64             );
65             };
66              
67 4 50       27 if ($@)
68             {
69 4     4   31 no strict 'refs';
  4         9  
  4         103  
70 4     4   17 no warnings 'redefine';
  4         8  
  4         208  
71 4         20 *{ 'new' } = fake_new();
  4         337  
72             }
73             }
74              
75             sub ACTION_test
76             {
77 0     0 0   my $self = shift;
78              
79             # don't let Module::Build::Base whine about missing tests
80 0           open( my $fh, '>' . devnull() );
81            
82 0           my $oldfh = select( $fh );
83 0 0         unless (reftype( $oldfh ))
84             {
85 4     4   22 no strict 'refs';
  4         9  
  4         3544  
86 0           $oldfh = \*$oldfh;
87             }
88 0           $self->notes( 'test_oldfh' => $oldfh );
89              
90 0           $self->SUPER( @_ );
91              
92             # now let it whine
93 0           select( $self->notes( 'test_oldfh' ) );
94             }
95              
96             sub find_test_files
97             {
98 0     0 0   my $self = shift;
99 0           my $strap = Test::Harness::Straps->new();
100 0           my $outfh = $self->notes( 'test_oldfh' );
101              
102 0           $self->notes( test_failures => [] );
103              
104             # XXX: this doesn't work
105 0           my $p = $self->{properties};
106 0           local @INC =
107             (
108 0           ( map { catdir( $p->{base_dir}, $self->blib(), $_ ) } qw( lib arch ) ),
109             @INC
110             );
111              
112             # this does
113 0           local $ENV{HARNESS_PERL_SWITCHES} = '-Mblib';
114              
115             # actually run the tests, collecting diagnostics
116 0           for my $file (@{ $self->SUPER( @_ ) })
  0            
117             {
118 0           my ($in, $out);
119              
120 0           my $pid = open3( $in, $out, $out, $strap->_command_line( $file ));
121 0           my %results = $strap->analyze_fh( $file, $out );
122              
123 0 0         if ($results{passing})
124             {
125 0 0         print $outfh "$file...ok\n" if $ENV{TEST_VERBOSE};
126 0           next;
127             }
128 0           $self->save_failure_details( $file, \%results );
129             }
130              
131 0           $self->report_failures();
132              
133             # don't let the tests leak out
134 0           return [];
135             }
136              
137             sub save_failure_details
138             {
139 0     0 0   my ($self, $file, $results) = @_;
140 0           my $failures = $self->notes( 'test_failures' );
141              
142 0           my @failures;
143              
144 0           for my $number ( 1 .. @{ $results->{details} } )
  0            
145             {
146 0           my $test = $results->{details}[$number - 1];
147              
148 0 0         next if $test->{actual_ok};
149              
150 0   0       push @failures,
      0        
151             {
152             number => $number,
153             description => $test->{name} || '',
154             diagnostics => $test->{diagnostics} || '',
155             };
156             }
157              
158 0           delete $results->{details};
159 0           $results->{file} = $file;
160 0           $results->{failures} = \@failures;
161 0           push @$failures, $results;
162             }
163              
164             sub report_failures
165             {
166 0     0     my $self = shift;
167 0           my $failures = $self->notes( 'test_failures' );
168 0           my $report = '';
169              
170 0           for my $test ( @$failures )
171             {
172 0           my $failed = $test->{seen} - $test->{ok};
173 0 0         next unless $failed;
174              
175 0           $report .= sprintf(
176             "Test failures in '%s' (%d/%d):\n",
177             $test->{file}, $failed, $test->{seen}
178             );
179              
180 0           for my $failure (@{ $test->{failures} })
  0            
181             {
182 0           $report .= sprintf(
183             " %d: %s\n\t%s",
184 0           @{$failure}{qw( number description diagnostics )}
185             );
186             }
187             }
188              
189 0 0         return $self->write_success_results() unless $report;
190              
191 0           my $version_fh;
192              
193 0 0         my $version = "\n\n" .
194             ( open( $version_fh, $^X . ' -V |' ) ?
195             join( '', <$version_fh> ) :
196             "Could not find version information for $^X on $^O: $!\n" );
197              
198 0           $self->write_report( $report, $version );
199 0           $self->write_failure_results( $report );
200             }
201              
202             sub write_success_results
203             {
204 0     0 0   my $self = shift;
205 0           my $oldfh = $self->notes( 'test_oldfh' );
206 0           print $oldfh "All tests passed...\n";
207             }
208              
209             sub write_report
210             {
211 0     0 0   my ($self, $report, $version) = @_;
212 0           my $file = $self->notes( 'report_file' );
213 0           my $outfh = $self->notes( 'test_oldfh' );
214              
215 0 0         open( my $out, '>', $file ) or die "Can't write $file: $!\n";
216 0           print $out $report, $version;
217             }
218              
219             sub write_failure_results
220             {
221 0     0 0   my ($self, $report) = @_;
222 0           my $outfh = $self->notes( 'test_oldfh' );
223 0           my $contact = $self->notes( 'report_address' );
224 0           my $report_file = $self->notes( 'report_file' );
225              
226 0           my $header = "Tests failed!\n";
227 0 0         $header .= "Please e-mail '$report_file' to $contact.\n" if $contact;
228              
229 0           print $outfh $header;
230 0 0         print $outfh $report if $ENV{TEST_VERBOSE};
231             }
232              
233             1;
234             __END__