File Coverage

blib/lib/Test/TAP.pm
Criterion Covered Total %
statement 55 60 91.6
branch 20 24 83.3
condition 3 3 100.0
subroutine 9 9 100.0
pod 2 2 100.0
total 89 98 90.8


line stmt bran cond sub pod time code
1             package Test::TAP;
2              
3 2     2   49784 use strict;
  2         4  
  2         68  
4 2     2   9 use Carp;
  2         3  
  2         147  
5 2     2   9 use Test::Builder;
  2         9  
  2         36  
6              
7 2     2   8 use vars '$VERSION';
  2         3  
  2         227  
8              
9             =head1 NAME
10              
11             Test::TAP - Test your TAP
12              
13             =head1 VERSION
14              
15             Version 0.03
16              
17             =cut
18              
19             $VERSION = '0.03';
20              
21             my $TEST = Test::Builder->new;
22              
23             sub import {
24 2     2   14 my $self = shift;
25 2         6 my $caller = caller;
26              
27 2         5 my @subs = qw/is_passing_tap is_failing_tap/;
28 2         5 foreach my $sub (@subs) {
29 2     2   9 no strict 'refs';
  2         2  
  2         1262  
30 4         9 *{"${caller}::$sub"} = \&{$sub};
  4         55  
  4         9  
31             }
32              
33 2         10 $TEST->exported_to($caller);
34 2         20 $TEST->plan(@_);
35             }
36              
37             =head1 SYNOPSIS
38              
39             use Test::TAP;
40              
41             is_passing_tap $tap1, 'TAP tests passed';
42             is_failing_tap $tap2, 'TAP tests failed';
43              
44             =head1 EXPORT
45              
46             =over 4
47              
48             =item * is_passing_tap
49              
50             =item * is_failing_tap
51              
52             =back
53              
54             =head1 DESCRIPTION
55              
56             Experimental module to tell if a TAP document is 'passing' or 'failing'.
57             We'll add more later, but for the time being, this module is for TAP
58             developers to experiment with.
59              
60             =head1 TESTS
61              
62             =head2 C
63              
64             is_passing_tap <<'END_TAP', '... TAP tests passed';
65             1..1
66             ok 1 This test passed
67             END_TAP
68              
69             Test passes if the string passed if the following criteria are met:
70              
71             =over 4
72              
73             =item * One plan
74              
75             You must have one and only one plan. It may be at the beginning or end of the
76             TAP, but not embedded. Plans found in nested TAP are acceptable.
77              
78             =item * Correct plan.
79              
80             Number of tests run must match the plan.
81              
82             =item * No failing tests.
83              
84             No 'not ok' tests may be found unless they are TODO tests.
85              
86             =back
87              
88             =head2 C
89              
90             is_failing_tap <<'END_TAP', '... TAP tests passed';
91             1..1
92             not ok 1 This test passed
93             END_TAP
94              
95             =cut
96              
97             sub is_passing_tap ($;$) {
98 4     4 1 15 my ( $tap, $test_name ) = @_;
99 4 50       10 croak "usage: is_passing_tap(tap,test_name)"
100             unless defined $tap;
101              
102 4 50       26 if ( my $error = _tap_failed($tap) ) {
103 0         0 $TEST->ok( 0, $test_name );
104 0         0 $TEST->diag("TAP failed:\n\n\t$error");
105 0         0 return;
106             }
107             else {
108 4         10 $TEST->ok( 1, $test_name );
109 4         937 return 1;
110             }
111             }
112              
113             sub is_failing_tap ($;$) {
114 5     5 1 20 my ( $tap, $test_name ) = @_;
115 5 50       11 croak "usage: is_failing_tap(tap,test_name)"
116             unless defined $tap;
117              
118 5 50       9 if ( my $error = _tap_failed($tap) ) {
119 5         21 $TEST->ok( 1, $test_name );
120 5         1149 return;
121             }
122             else {
123 0         0 $TEST->ok( 0, $test_name );
124 0         0 return 1;
125             }
126             }
127              
128             sub _tap_failed {
129 9     9   11 my $tap = shift;
130 9         28 my $plan_re = qr/1\.\.(\d+)/;
131 9         22 my $test_re = qr/(?:not )?ok/;
132 9         10 my $failed;
133 9         10 my $core_tap = '';
134 9         26 foreach ( split "\n" => $tap ) {
135 32 100       62 if (/^not ok/) { # TODO tests are not failures
136 2 100       11 $failed++
137             unless m/^ ( [^\\\#]* (?: \\. [^\\\#]* )* )
138             \# \s* TODO \b \s* (.*) $/ix
139             }
140 32 100       222 $core_tap .= "$_\n" if /^(?:$plan_re|$test_re)/;
141             }
142 9         14 my $plan;
143 9 100 100     69 if ( $core_tap =~ /^$plan_re/ or $core_tap =~ /$plan_re$/ ) {
144 7         16 $plan = $1;
145             }
146 9 100       26 return 'No plan found' unless defined $plan;
147 7 100       19 return "Failed $failed out of $plan tests" if $failed;
148              
149 6         7 my $plans_found = 0;
150 6         58 $plans_found++ while $core_tap =~ /^$plan_re/gm;
151 6 100       18 return "$plans_found plans found" if $plans_found > 1;
152              
153 5         5 my $tests = 0;
154 5         61 $tests++ while $core_tap =~ /^$test_re/gm;
155 5 100       30 return "Planned $plan tests and found $tests tests" if $tests != $plan;
156              
157 4         17 return;
158             }
159              
160             =head1 AUTHOR
161              
162             Curtis "Ovid" Poe, C<< >>
163              
164             =head1 BUGS
165              
166             Please report any bugs or feature requests to C, or
167             through the web interface at
168             L. I will be
169             notified, and then you'll automatically be notified of progress on your bug as
170             I make changes.
171              
172             =head1 SEE ALSO
173              
174             C, C
175              
176             =head1 ACKNOWLEDGEMENTS
177              
178              
179             =head1 COPYRIGHT & LICENSE
180              
181             Copyright 2008 Curtis "Ovid" Poe, all rights reserved.
182              
183             This program is free software; you can redistribute it and/or modify it
184             under the same terms as Perl itself.
185              
186             =cut
187              
188             1;
189