File Coverage

blib/lib/App/Prove/State/Result.pm
Criterion Covered Total %
statement 69 71 97.1
branch 8 10 80.0
condition 5 9 55.5
subroutine 17 17 100.0
pod 9 9 100.0
total 108 116 93.1


line stmt bran cond sub pod time code
1             package App::Prove::State::Result;
2              
3 8     8   28 use strict;
  8         12  
  8         204  
4 8     8   25 use warnings;
  8         9  
  8         176  
5 8     8   27 use Carp 'croak';
  8         10  
  8         301  
6              
7 8     8   3255 use App::Prove::State::Result::Test;
  8         15  
  8         298  
8              
9 8     8   40 use constant STATE_VERSION => 1;
  8         9  
  8         2316  
10              
11             =head1 NAME
12              
13             App::Prove::State::Result - Individual test suite results.
14              
15             =head1 VERSION
16              
17             Version 3.39
18              
19             =cut
20              
21             our $VERSION = '3.39';
22              
23             =head1 DESCRIPTION
24              
25             The C command supports a C<--state> option that instructs it to
26             store persistent state across runs. This module encapsulates the results for a
27             single test suite run.
28              
29             =head1 SYNOPSIS
30              
31             # Re-run failed tests
32             $ prove --state=failed,save -rbv
33              
34             =cut
35              
36             =head1 METHODS
37              
38             =head2 Class Methods
39              
40             =head3 C
41              
42             my $result = App::Prove::State::Result->new({
43             generation => $generation,
44             tests => \%tests,
45             });
46              
47             Returns a new C instance.
48              
49             =cut
50              
51             sub new {
52 89     89 1 4251 my ( $class, $arg_for ) = @_;
53 89   50     241 $arg_for ||= {};
54 89         322 my %instance_data = %$arg_for; # shallow copy
55 89         386 $instance_data{version} = $class->state_version;
56 89   50     279 my $tests = delete $instance_data{tests} || {};
57 89         187 my $self = bless \%instance_data => $class;
58 89         329 $self->_initialize($tests);
59 89         253 return $self;
60             }
61              
62             sub _initialize {
63 89     89   130 my ( $self, $tests ) = @_;
64 89         112 my %tests;
65 89         376 while ( my ( $name, $test ) = each %$tests ) {
66 90         99 $tests{$name} = $self->test_class->new(
67             { %$test,
68             name => $name
69             }
70             );
71             }
72 89         307 $self->tests( \%tests );
73 89         147 return $self;
74             }
75              
76             =head2 C
77              
78             Returns the current version of state storage.
79              
80             =cut
81              
82 91     91 1 257 sub state_version {STATE_VERSION}
83              
84             =head2 C
85              
86             Returns the name of the class used for tracking individual tests. This class
87             should either subclass from C or provide an
88             identical interface.
89              
90             =cut
91              
92             sub test_class {
93 93     93 1 584 return 'App::Prove::State::Result::Test';
94             }
95              
96             my %methods = (
97             generation => { method => 'generation', default => 0 },
98             last_run_time => { method => 'last_run_time', default => undef },
99             );
100              
101             while ( my ( $key, $description ) = each %methods ) {
102             my $default = $description->{default};
103 8     8   108 no strict 'refs';
  8         16  
  8         3299  
104             *{ $description->{method} } = sub {
105 151     151   172 my $self = shift;
106 151 50       362 if (@_) {
107 0         0 $self->{$key} = shift;
108 0         0 return $self;
109             }
110 151   66     578 return $self->{$key} || $default;
111             };
112             }
113              
114             =head3 C
115              
116             Getter/setter for the "generation" of the test suite run. The first
117             generation is 1 (one) and subsequent generations are 2, 3, etc.
118              
119             =head3 C
120              
121             Getter/setter for the time of the test suite run.
122              
123             =head3 C
124              
125             Returns the tests for a given generation. This is a hashref or a hash,
126             depending on context called. The keys to the hash are the individual
127             test names and the value is a hashref with various interesting values.
128             Each k/v pair might resemble something like this:
129              
130             't/foo.t' => {
131             elapsed => '0.0428488254547119',
132             gen => '7',
133             last_pass_time => '1219328376.07815',
134             last_result => '0',
135             last_run_time => '1219328376.07815',
136             last_todo => '0',
137             mtime => '1191708862',
138             seq => '192',
139             total_passes => '6',
140             }
141              
142             =cut
143              
144             sub tests {
145 107     107 1 131 my $self = shift;
146 107 100       244 if (@_) {
147 89         165 $self->{tests} = shift;
148 89         143 return $self;
149             }
150 18         17 my %tests = %{ $self->{tests} };
  18         49  
151 18         61 my @tests = sort { $a->sequence <=> $b->sequence } values %tests;
  190         244  
152 18 50       53 return wantarray ? @tests : \@tests;
153             }
154              
155             =head3 C
156              
157             my $test = $result->test('t/customer/create.t');
158              
159             Returns an individual C instance for the
160             given test name (usually the filename). Will return a new
161             C instance if the name is not found.
162              
163             =cut
164              
165             sub test {
166 150     150 1 453 my ( $self, $name ) = @_;
167 150 100       316 croak("test() requires a test name") unless defined $name;
168              
169 149   50     200 my $tests = $self->{tests} ||= {};
170 149 100       174 if ( my $test = $tests->{$name} ) {
171 146         218 return $test;
172             }
173             else {
174 3         17 my $test = $self->test_class->new( { name => $name } );
175 3         10 $self->{tests}->{$name} = $test;
176 3         13 return $test;
177             }
178             }
179              
180             =head3 C
181              
182             Returns an list of test names, sorted by run order.
183              
184             =cut
185              
186             sub test_names {
187 17     17 1 11 my $self = shift;
188 17         19 return map { $_->name } $self->tests;
  102         126  
189             }
190              
191             =head3 C
192              
193             $result->remove($test_name); # remove the test
194             my $test = $result->test($test_name); # fatal error
195              
196             Removes a given test from results. This is a no-op if the test name is not
197             found.
198              
199             =cut
200              
201             sub remove {
202 1     1 1 2 my ( $self, $name ) = @_;
203 1         2 delete $self->{tests}->{$name};
204 1         2 return $self;
205             }
206              
207             =head3 C
208              
209             Returns the number of tests for a given test suite result.
210              
211             =cut
212              
213 15     15 1 11 sub num_tests { keys %{ shift->{tests} } }
  15         46  
214              
215             =head3 C
216              
217             Returns a hashref of raw results, suitable for serialization by YAML.
218              
219             =cut
220              
221             sub raw {
222 1     1 1 440 my $self = shift;
223 1         4 my %raw = %$self;
224              
225 1         2 my %tests;
226 1         3 for my $test ( $self->tests ) {
227 6         8 $tests{ $test->name } = $test->raw;
228             }
229 1         2 $raw{tests} = \%tests;
230 1         4 return \%raw;
231             }
232              
233             1;