File Coverage

blib/lib/Test/Proto/TestRunner.pm
Criterion Covered Total %
statement 103 104 99.0
branch 32 36 88.8
condition 7 9 77.7
subroutine 24 24 100.0
pod 12 13 92.3
total 178 186 95.7


line stmt bran cond sub pod time code
1             package Test::Proto::TestRunner;
2 14     14   41250 use 5.008;
  14         48  
  14         552  
3 14     14   88 use strict;
  14         28  
  14         391  
4 14     14   85 use warnings;
  14         25  
  14         847  
5 14     14   14155 use overload 'bool' => sub { $_[0]->value };
  14     7654   9248  
  14         152  
  7654         215913  
6 14     14   9204 use Moo;
  14         161633  
  14         104  
7 14     14   30523 use Object::ID;
  14         103447  
  14         99  
8 14     14   1550 use Test::Proto::Common ();
  14         34  
  14         19983  
9              
10             sub _zero {
11 53630     53630   1454942 sub { 0; }
12 70     70   493 }
13              
14             =head1 NAME
15              
16             Test::Proto::TestRunner - Embodies a run through a test
17              
18             =head1 SYNOPSIS
19              
20             my $runner = Test::Proto::TestRunner->new(test_case=>$testCase);
21             my $subRunner $runner->subtest;
22             $subRunner->pass;
23             $runner->done();
24              
25             Note that it is a Moo class.
26              
27             Unless otherwise specified, the return value is itself.
28              
29             =cut
30              
31             sub BUILD {
32 10726     10726 0 60464 my $self = shift;
33 10726         28443 $self->inform_formatter('new');
34             }
35              
36             =head2 ATTRIBUTES
37              
38             All of these attributes are chainable as setters.
39              
40             =cut
41              
42             =head3 subject
43              
44             Returns the test subject
45              
46             =cut
47              
48             has 'subject' => is => 'rw';
49              
50             =head3 test_case
51              
52             Returns the test case or the prototype
53              
54             =cut
55              
56             has 'test_case' => is => 'rw';
57              
58             =head3 parent
59              
60             Returns the parent of the test.
61              
62             =cut
63              
64             has 'parent' => is => 'rwp',
65             weak_ref => 1;
66              
67             =head3 is_complete
68              
69             Returns C<1> if the test run has finished, C<0> otherwise.
70              
71             =cut
72              
73             has 'is_complete' => is => 'rwp',
74             default => _zero;
75              
76             =head3 value
77              
78             Returns C<0> if the test run has failed or exception, C<1> otherwise.
79              
80             =cut
81              
82             has 'value' => is => 'rw',
83             default => _zero;
84              
85             =head3 skipped_tags
86              
87             If any test case or prototype has one of the tags in this list, the runner will skip it.
88              
89             =cut
90              
91             has 'skipped_tags' => is => 'rw',
92             default => sub { [] };
93              
94             =head3 required_tags
95              
96             If this list is not empty, then unless a test case or prototype has a tag in this list, the runner will skip it.
97              
98             =cut
99              
100             has 'required_tags' => is => 'rw',
101             default => sub { [] };
102              
103             =head3 is_exception
104              
105             Returns C<1> if the test run has run into an exception, C<0> otherwise.
106              
107             =cut
108              
109             has 'is_exception' => is => 'rwp',
110             default => _zero;
111              
112             =head3 is_info
113              
114             Returns C<1> if the result is for information purposes, C<0> otherwise.
115              
116             =cut
117              
118             has 'is_info' => is => 'rwp',
119             default => _zero;
120              
121             =head3 is_skipped
122              
123             Returns C<1> if the test case was skipped, C<0> otherwise.
124              
125             =cut
126              
127             has 'is_skipped' => is => 'rwp',
128             default => _zero;
129              
130             =head3 children
131              
132             Returns an arrayref
133              
134             =cut
135              
136             has 'children' => is => 'rw',
137             default => sub { [] };
138              
139             =head3 status_message
140              
141             This is a string which indicates the reason for skipping, exception info, etc.
142              
143             =cut
144              
145             has 'status_message' => is => 'rw',
146             default => sub { '' };
147              
148             =head3 formatter
149              
150             Returns the formatter used.
151              
152             =cut
153              
154             has 'formatter' => is => 'rw'; # Test::Proto::Common::Formatter->new;
155              
156             around qw(subject test_case parent is_complete skipped_tags required_tags children value is_exception is_info is_skipped children status_message ), \&Test::Proto::Common::chainable;
157              
158             =head2 METHODS
159              
160             =head3 complete
161              
162             $self->complete(0);
163             $self->complete(0, 'Something went wrong');
164              
165             Declares the test run is complete. It is intended that this is only called by the other methods C, C, C, C, C, C.
166              
167             =cut
168              
169             sub complete {
170 10723     10723 1 16911 my ( $self, $value, $message ) = @_;
171 10723 100       282639 if ( $self->is_complete ) {
172 1 50       6 warn "Tried to complete something that was already complete (a " . $self->status . "). (Tried with value=> " . ( defined $value ? $value : '[undefined]' ) . ", message=>" . ( defined $message ? $message : '[undefined]' ) . ")";
    50          
173 1         5 return $self;
174             }
175 10722         276621 $self->value($value);
176 10722 100       154468 $self->status_message($message) if defined $message;
177 10722         24083 $self->_set_is_complete(1);
178 10722         22808 $self->inform_formatter('done');
179 10722         17214 return $self;
180             }
181              
182             =head3 subtest
183              
184             Creates and returns a child, which is another TestRunner. The child keeps the same formatter, subject, and test_case as the parent. The child is added to the parent's list of events.
185              
186             =cut
187              
188             sub subtest {
189 9734     9734 1 12472 my $self = shift;
190 9734         260820 my $event = __PACKAGE__->new( {
191             formatter => $self->formatter,
192             subject => $self->subject,
193             test_case => $self->test_case,
194             skipped_tags => $self->skipped_tags,
195             required_tags => $self->required_tags,
196             parent => $self,
197             @_
198             }
199             );
200 9734         89278 $self->add_event($event);
201 9734         30733 return $event;
202             }
203              
204             =head3 add_event
205              
206             Adds an event to the runner.
207              
208             =cut
209              
210             sub add_event {
211 9741     9741 1 14808 my ( $self, $event ) = @_;
212 9741 100       250273 if ( $self->is_complete ) {
213 2         185 warn "Tried to add an event to a TestRunner which is already complete";
214             }
215             else {
216 9739 50       22475 unless ( defined $event ) {
217 0         0 die('tried to add an undefined event');
218             }
219 9739         10944 push @{ $self->children }, $event;
  9739         243911  
220             }
221 9741         17717 return $self;
222             }
223              
224             =head3 done
225              
226             $self->done;
227             $self->done ('Completed check of widgets');
228              
229             Declares that the test run is complete, and determines if the result is a pass or a fail - if there are any failures, then the result is deemed to be a failure.
230              
231             =cut
232              
233             sub done {
234 6362     6362 1 12143 my ( $self, $message ) = @_;
235 6362 100       7662 return $self->exception if scalar grep { $_->is_exception } @{ $self->children() };
  7499         196706  
  6362         168590  
236 6352 100       17872 $self->complete( $self->_count_fails ? 0 : 1, $message );
237 6352         18083 return $self;
238             }
239              
240             sub _count_fails {
241 6352     6352   7964 my $self = shift;
242 6352         8375 return scalar grep { !$_->value } @{ $self->children() };
  7489         191292  
  6352         165929  
243             }
244              
245             # add_(pass|fail|diag|exception) to spec further
246              
247             =head3 pass
248              
249             $self->pass;
250              
251             Declares that the test run is complete, and declares the result to be a pass, irrespective of what the results of the subtests were.
252              
253             =cut
254              
255             sub pass {
256 1929     1929 1 3369 my ( $self, $message ) = @_;
257 1929         5578 $self->complete( 1, $message );
258 1929         13947 return $self;
259             }
260              
261             =head3 fail
262              
263             $self->fail;
264              
265             Declares that the test run is complete, and declares the result to be a failure, irrespective of what the results of the subtests were.
266              
267             =cut
268              
269             sub fail {
270 627     627 1 1622 my ( $self, $message ) = @_;
271 627         2106 $self->complete( 0, $message );
272 627         5666 return $self;
273             }
274              
275             =head3 diag
276              
277             $self->diag;
278              
279             Declares that the test run is complete, and declares that it is not a result but a diagnostic message, irrespective of what the results of the subtests were.
280              
281             =cut
282              
283             sub diag {
284 1794     1794 1 3105 my ( $self, $message ) = @_;
285 1794         4002 $self->_set_is_info(1);
286 1794         3850 $self->complete( 1, $message );
287 1794         4161 return $self;
288             }
289              
290             =head3 skip
291              
292             $self->skip;
293              
294             Declares that the test run is complete, but that it was skipped.
295              
296             =cut
297              
298             sub skip {
299 4     4 1 19 my ( $self, $message ) = @_;
300 4         13 $self->_set_is_skipped(1);
301 4         11 $self->complete( 1, $message );
302 4         15 return $self;
303             }
304              
305             =head3 exception
306              
307             $self->exception;
308              
309             Declares that the test run is complete, and declares the result to be an exception, irrespective of what the results of the subtests were.
310              
311             =cut
312              
313             sub exception {
314 17     17 1 48 my ( $self, $message ) = @_;
315 17         47 $self->_set_is_exception(1);
316 17         51 $self->complete( 0, $message );
317 17         58 return $self;
318             }
319              
320             =head3 inform_formatter
321              
322             $self->inform_formatter;
323              
324             Used internally to send events to the formatter. The two events currently permitted are 'new' and 'done'.
325              
326             =cut
327              
328             sub inform_formatter {
329 21448     21448 1 29649 my ($self) = @_;
330 21448         39213 my $formatter = $self->formatter;
331 21448 100       282986 if ( defined $formatter ) {
332 218         704 $formatter->event(@_);
333             }
334             }
335              
336             =head3 status
337              
338             $self->status;
339              
340             Useful to summarise the status of the TestRunner. Possible values are: FAIL, PASS, INFO, SKIPPED, EXCEPTION, INCOMPLETE.
341              
342             =cut
343              
344             sub status {
345 117     117 1 3368 my ($self) = @_;
346 117 100       11456 return 'INCOMPLETE' unless $self->is_complete;
347 116 100       3002 return 'EXCEPTION' if $self->is_exception;
348 115 100       3163 return 'SKIPPED' if $self->is_skipped;
349 114 100       3116 return 'INFO' if $self->is_info;
350 112 100       2793 return 'PASS' if $self->value;
351 1         8 return 'FAIL';
352             }
353              
354             =head3 run_test
355              
356             $self->run_test($test, $proto);
357              
358             This method runs a particular test in the object's script, and returns the subtest. It is called by the C<< Test::Proto::Base::run_tests >> and should only be called by subclasses of L which override that method.
359              
360             This is documented for information purposes only and is not intended to be used except in the maintainance of C itself.
361              
362             =cut
363              
364             sub run_test {
365 4067     4067 1 7069 my ( $self, $test, $proto ) = @_;
366 4067         107813 my $runner = $self->subtest(
367             test_case => $test,
368             subject => $self->subject
369             );
370 4067         6694 foreach my $tag ( @{ $self->skipped_tags } ) {
  4067         106549  
371 2 100 66     10 if ( $test->has_tag($tag) or $proto->has_tag($tag) ) {
372 1         8 return $runner->skip( 'Skipping tag ' . $tag );
373             }
374             }
375 4066         6132 foreach my $tag ( @{ $self->required_tags } ) {
  4066         105944  
376 2 100 66     8 if ( $test->has_tag($tag) or $proto->has_tag($tag) ) {
377 1         21 $runner->required_tags( [] );
378 1         3 last;
379             }
380             }
381 4066 100 100     6316 return $runner->skip( 'None of the required tags (' . join( '', @{ $self->required_tags() } ) . ') found' ) if @{ $self->required_tags() } and @{ $runner->required_tags() };
  1         22  
  4066         104776  
  2         39  
382 4065         116127 my $result = $test->code->($runner);
383 4065 50       114356 $runner->exception("Test execution did not complete.") unless $runner->is_complete;
384 4065         12812 return $runner;
385             }
386              
387             =head3 object_id, object_uuid
388              
389             Test::Proto::TestRunner implements L. This is used by formatters.
390              
391             =cut
392              
393             1;
394