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; |