File Coverage

blib/lib/Test/TAP/Model/File.pm
Criterion Covered Total %
statement 88 89 98.8
branch 23 28 82.1
condition 3 3 100.0
subroutine 34 35 97.1
pod 18 19 94.7
total 166 174 95.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package Test::TAP::Model::File;
4              
5 6     6   25793 use strict;
  6         11  
  6         210  
6 6     6   48 use warnings;
  6         12  
  6         167  
7              
8 6     6   15088 use Test::TAP::Model::Subtest;
  6         17  
  6         172  
9 6     6   39 use List::Util (); # don't import max, we have our own. We use it fully qualified
  6         10  
  6         140  
10              
11 6     6   36 use overload '""' => "name", '==' => "equal";
  6         9  
  6         37  
12              
13             use Method::Alias (
14 24         52 (map { ($_ => 'cases') } qw/seen_tests seen test_cases subtests/),
  6         16  
15 6         15 (map { ($_ => 'ok_tests') } qw/passed_tests/),
16 6         18 (map { ($_ => 'nok_tests') } qw/failed_tests/),
17 6         15 (map { ($_ => 'planned') } qw/max/),
18 6         39 (map { ($_ => 'ok') } qw/passed/),
19 6         16 (map { ($_ => 'nok') } qw/failed/),
20 6     6   6651 );
  6         2502  
21              
22             # TODO test this more thoroughly, probably with Devel::Cover
23              
24             sub new {
25 21     21 1 80 my $pkg = shift;
26 21         35 my $struct = shift;
27 21         232 bless { struct => $struct }, $pkg; # don't bless the structure, it's not ours to mess with
28             }
29              
30             # predicates about the test file
31 31     31 1 1692 sub ok { $_[0]{struct}{results}->passing };
32 3     3 1 1039 sub nok { !$_[0]->ok };
33 3     3 1 9128 sub skipped { defined($_[0]{struct}{results}->skip_all) };
34             sub bailed_out {
35 3 50   3 1 542 my $event = $_[0]{struct}{events}[-1] or return;
36 3 50       10 return unless exists $event->{type};
37 3         14 return $event->{type} eq "bailout";
38             }
39              
40             # member data queries
41 0     0 1 0 sub name { $_[0]{struct}{file} }
42              
43             # utility methods for extracting tests.
44 56     56 1 229 sub subtest_class { "Test::TAP::Model::Subtest" }
45 33 100   33   58 sub _mk_objs { my $self = shift; wantarray ? map { $self->subtest_class->new($_) } @_ : @_ }
  33         108  
  56         120  
46             sub _test_structs {
47 33     33   47 my $self = shift;
48 33         118 my $max = $self->{struct}{results}->max;
49              
50             # cases is an array of *copies*... that's what the map is about
51 33 50       169 my @cases = grep { exists $_->{type} and $_->{type} eq "test" } @{ $self->{struct}{events} };
  89         698  
  33         97  
52              
53 33 50       91 if (defined $max){
54 33 100       122 if ($max > @cases){
    100          
55             # add failed stubs for tests missing from plan
56 2         8 my %bailed = (
57             type => "test",
58             ok => 0,
59             line => "stub",
60             );
61              
62 2         6 for my $num (@cases + 1 .. $max) {
63 2         13 push @cases, { %bailed, num => $num };
64             }
65             } elsif (@cases > $max) {
66             # mark extra tests as unplanned
67 2         4 my $diff = @cases - $max;
68 2         11 for (my $i = $diff; $i; $i--){
69 2         7 $cases[-$i]{unplanned} = 1;
70             }
71             }
72             }
73              
74 33         87 @cases;
75             }
76             sub _c {
77 152     152   581 my $self = shift;
78 152         281 my $sub = shift;
79 152         267 my $scalar = shift;
80 152 100 100     3069 return $scalar if not wantarray and defined $scalar; # if we have a precomputed scalar
81 33         75 $self->_mk_objs(grep { &$sub } $self->_test_structs);
  89         142  
82             }
83              
84             # queries about the test cases
85 6     6 1 746 sub planned { $_[0]{struct}{results}->max };
86              
87             sub cases {
88 82     82 1 4896 my @values = map { $_[0]{struct}{results}->$_ } qw/seen max/;
  164         1427  
89 82         881 my $scalar = List::Util::max(@values);
90 82     45   501 $_[0]->_c(sub { 1 }, $scalar)
  45         103  
91             };
92 2     2 1 8 sub actual_cases { $_[0]->_c(sub { $_->{line} ne "stub" }, $_[0]{struct}{results}->seen) }
  4     4   420  
93 6     6 1 18 sub ok_tests { $_[0]->_c(sub { $_->{ok} }, $_[0]{struct}{results}->ok) };
  37     37   1635  
94 6     6 1 23 sub nok_tests { $_[0]->_c(sub { not $_->{ok} }, $_[0]->seen - $_[0]->ok_tests )};
  7     7   2732  
95 6     6 1 22 sub todo_tests { $_[0]->_c(sub { $_->{todo} }, $_[0]{struct}{results}->todo) }
  9     9   1607  
96 6     6 1 17 sub skipped_tests { $_[0]->_c(sub { $_->{skip} }, $_[0]{struct}{results}->skip) }
  7     7   1417  
97 18 100   18 1 73 sub unexpectedly_succeeded_tests { $_[0]->_c(sub { $_->{todo} and $_->{actual_ok} }) }
  6     6   1133  
98              
99             sub ratio {
100 11     11 1 669 my $self = shift;
101 11 100       319 $self->seen ? $self->ok_tests / $self->seen : ($self->ok ? 1 : 0); # no tests is an error
    100          
102             }
103              
104             sub percentage {
105 2     2 1 6 my $self = shift;
106 2         7 sprintf("%.2f%%", 100 * $self->ratio);
107             }
108              
109 2 100   2 1 21 sub pre_diag { $_[0]{struct}{pre_diag} || ""}
110              
111             sub equal {
112 2     2 0 5 my $self = shift;
113 2         3 my $other = shift;
114              
115             # number of sub-tests
116 2 50       57 return unless $self->seen == $other->seen;
117              
118             # values of subtests
119 2         11 my @self = $self->cases;
120 2         7 my @other = $other->cases;
121              
122 2         10 while (@self) {
123 3 100       50 return unless (pop @self) == (pop @other);
124             }
125              
126 1         6 1;
127             }
128              
129             __PACKAGE__
130              
131             __END__