File Coverage

blib/lib/Test/Proto/Base.pm
Criterion Covered Total %
statement 87 87 100.0
branch 12 14 85.7
condition 5 6 83.3
subroutine 21 21 100.0
pod 6 6 100.0
total 131 134 97.7


line stmt bran cond sub pod time code
1             package Test::Proto::Base;
2 13     13   98226 use 5.008;
  13         48  
  13         555  
3 13     13   71 use strict;
  13         26  
  13         394  
4 13     13   76 use warnings;
  13         22  
  13         359  
5 13     13   4970 use Test::Proto::Common;
  13         31  
  13         966  
6 13     13   7873 use Test::Proto::TestRunner;
  13         50  
  13         448  
7 13     13   10988 use Test::Proto::Formatter::TestBuilder;
  13         35  
  13         137  
8 13     13   15704 use Test::Proto::TestCase;
  13         50  
  13         430  
9 13     13   94 use Moo;
  13         26  
  13         67  
10             use overload
11 13         178 '&' => \&_overload_AND,
12             '|' => \&_overload_OR,
13             '^' => \&_overload_XOR,
14             '!' => \&_overload_NOT,
15 13     13   4893 ;
  13         29  
16             with('Test::Proto::Role::Value');
17             with('Test::Proto::Role::Tagged');
18             our $VERSION = '0.027';
19              
20             =pod
21              
22             =head1 NAME
23              
24             Test::Proto::Base - Base Class for Test Prototypes
25              
26             =head1 SYNOPSIS
27              
28             my $p = Test::Proto::Base->new->is_eq(-5);
29             $p->ok ($temperature) # will fail unless $temperature is -5
30             $p->ok ($score) # you can use the same test multple times
31             ok($p->validate($score)) # If you like your "ok"s first
32              
33             This is a base class for test prototypes.
34              
35             Throughout this documentation, C

will be used as a shorthand for C<< Test::Proto::Base->new >>.

36              
37             =cut
38              
39             =head1 METHODS
40              
41             =head2 PUBLIC METHODS
42              
43             These are the methods intended for use when execcuting tests. All the methods for writing tests can be found at L.
44              
45             =cut
46              
47             =head3 validate
48              
49             my $result = $p->validate($subject);
50             warn $result unless $result;
51              
52             Runs through the tests in the prototype and checks that they all pass. It returns a TestRunner which evaluates true or false accordingly.
53              
54             If you have an existing TestRunner, you can pass it that as well;
55              
56             my $result = $p->validate($subject, $context);
57              
58             EXPERIMENTAL: If no argument is passed, $_ will be used.
59              
60             =cut
61              
62             sub validate {
63 3123     3123 1 11172 my ( $self, $subject, $context ) = @_;
64 3123 100       9003 $subject = $_ unless exists $_[1];
65 3123 100 100     17919 if ( !defined $context or !CORE::ref($context) ) { # if context is not a TestRunner
66 959         1677 my $reason = $context;
67 959         24544 $context = Test::Proto::TestRunner->new( subject => $subject );
68 959 100       7624 if ( defined $reason ) {
69 1         4 $context->subtest->diag($reason);
70             }
71             }
72             else {
73 2164         56536 $context->subject($subject);
74             }
75 3123         9934 $self->run_tests($context);
76 3123         9801 $context->done;
77 3123         14962 return $context;
78             }
79              
80             =head3 ok
81              
82             $p->ok($subject, $context)
83              
84             Works like validate, only produces a Test::Builder-compatible TAP output.
85              
86             =cut
87              
88             sub ok {
89 2     2 1 4 my ( $self, $subject, $context ) = @_;
90 2         4 my $reason = $context;
91 2 50 66     63 $context = Test::Proto::TestRunner->new( formatter => Test::Proto::Formatter::TestBuilder->new() ) unless ( ( defined $context ) and ( CORE::ref $context ) );
92 2 100       14 if ( defined $reason ) {
93 1         6 $context->subtest->diag($reason);
94             }
95 2         14 $self->validate( $subject, $context );
96             }
97              
98             =head3 clone
99              
100             This method returns a copy of the current object. The new object can have tests added without affecting the existing test. However, existing tests are not cloned, so if you want to tag them, you will need to clone them too.
101              
102             =cut
103              
104             sub clone {
105 4     4 1 17 my $self = shift;
106 4         9 my $pkg = CORE::ref $self;
107 4         11 my %args = ( map { $_ => [ @{ $self->$_ } ] } qw(natural_script user_script tags) );
  12         16  
  12         61  
108 4         183 return $pkg->new(%args);
109             }
110              
111             =head2 OPERATOR OVERLOADING
112              
113             Prototypes can be combined with the operators C<&>, C<|>, C<^>, and negated: C. In all cases, a new prototype is returned.
114              
115             $x & $y => p->all_of([$x, $y])
116             $x | $y => p->any_of([$x, $y])
117             $x ^ $y => p->some_of([$x, $y], 1)
118             !$x => p->none_of([$x])
119              
120             Remember that this only works with prototypes. C<'A' & 'B'> still returns C<'@'>.
121              
122             =cut
123              
124             =head2 PROTOTYPER METHODS
125              
126             These are for documentation purposes only.
127              
128             =cut
129              
130             =head3 natural_type
131              
132             This roughly corresponds to C. Useful for indicating what sort of element you're expecting.
133              
134             This is documented for information purposes only and is not intended to be used except in the maintainance of C itself.
135              
136             =cut
137              
138             has natural_type => (
139             is => 'rw',
140             default => sub { '' },
141             ,
142             ); # roughly corresponds to ref.
143              
144             =head3 natural_script
145              
146             These are tests common to the whole prototype which need not be repeated if two similar scripts are joined together. Normally, this should only be modified by the prototype class.
147              
148             This is documented for information purposes only and is not intended to be used except in the maintainance of C itself.
149              
150             =cut
151              
152             has natural_script => (
153             is => 'rw',
154             default => sub { [] },
155             );
156              
157             =head3 user_script
158              
159             These are the tests which the user (specifically, the test script author) has added by a method call. Normally, these should empty in a class but may be present in an instance of an object.
160              
161             This is documented for information purposes only and is not intended to be used except in the maintainance of C itself.
162              
163             =cut
164              
165             has user_script => (
166             is => 'rw',
167             default => sub { [] },
168             );
169              
170             =head3 script
171              
172             This method returns an arrayref containing the contents of the C and the C, i.e. all the tests in the object that are due to be run when C<< ->ok() >> is called.
173              
174             =cut
175              
176             sub script {
177 3123     3123 1 4949 my $self = shift;
178 3123         4389 return [ @{ $self->natural_script }, @{ $self->user_script }, ];
  3123         8845  
  3123         15016  
179             }
180              
181             =head3 add_test
182              
183             This method adds a test to the current object, specifically to the C, and returns the prototype object.
184              
185             This is documented for information purposes only and is not intended to be used except in the maintainance of C itself.
186              
187             =cut
188              
189             sub add_test {
190 4063     4063 1 8648 my ( $self, $name, $data, $reason ) = @_;
191 4063         7004 my $package = CORE::ref($self);
192              
193 4063         11617 my $testMethodName = $package . '::' . ${Test::Proto::Common::TEST_PREFIX} . $name;
194             my $code = sub {
195 4065     4065   6292 my $runner = shift;
196 4065         110210 my $subject = $runner->subject;
197             {
198 13     13   9063 no strict 'refs';
  13         26  
  13         5851  
  4065         6455  
199 4065         6832 eval { &{$testMethodName}( $runner, $data, $reason ); };
  4065         5439  
  4065         26058  
200 4065 100       24526 $runner->exception( "Failed during $name\n" . $@ ) if $@;
201             }
202 4063         22307 };
203 4063         6618 push @{ $self->user_script },
  4063         107451  
204             Test::Proto::TestCase->new(
205             name => $name,
206             code => $code,
207             data => $data,
208             reason => $reason,
209             );
210 4063         53804 return $self;
211             }
212              
213             =head3 run_tests
214              
215             $self->run_tests($subject, $context);
216              
217             This method runs all the tests in the prototype object's script (simply calling the C<< ->run_test >> method on each), and returns the prototype object.
218              
219             This is documented for information purposes only and is not intended to be used except in the maintainance of C itself.
220              
221             =cut
222              
223             sub run_tests {
224 3123     3123 1 5273 my ( $self, $context ) = @_;
225 3123         10958 my $runner = $context->subtest( test_case => $self );
226 3123         4542 foreach my $test ( @{ $self->script } ) {
  3123         9215  
227              
228             # $self->run_test($test, $runner);
229 4067         15181 $runner->run_test( $test, $self );
230 4067 50       107438 return $self if $runner->is_exception;
231             }
232 3123         20517 $runner->done( "A " . ( ref $self ) . " must pass all its subtests." );
233 3123         6846 return $self;
234             }
235              
236             =head1 OTHER INFORMATION
237              
238             For author, version, bug reports, support, etc, please see L.
239              
240             =cut
241              
242             sub _overload_AND {
243 2     2   5 my ( $left, $right ) = @_;
244 2         50 return __PACKAGE__->new->all_of( [ $left, $right ] );
245             }
246              
247             sub _overload_OR {
248 2     2   6 my ( $left, $right ) = @_;
249 2         53 return __PACKAGE__->new->any_of( [ $left, $right ] );
250             }
251              
252             sub _overload_XOR {
253 2     2   7 my ( $left, $right ) = @_;
254 2         53 return __PACKAGE__->new->some_of( [ $left, $right ], 1 );
255             }
256              
257             sub _overload_NOT {
258 2     2   5 my ($left) = @_;
259 2         52 return __PACKAGE__->new->none_of( [$left], 1 );
260             }
261              
262             1;