line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Lazy::Tester; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
11
|
use warnings; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
65
|
|
4
|
2
|
|
|
2
|
|
10
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
93
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 NAME |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
Test::Lazy::Tester |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 SYNOPSIS |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use Test::Lazy::Tester; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
$tester = Test::Lazy::Tester->new; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# Will evaluate the code and check it: |
17
|
|
|
|
|
|
|
$tester->try('qw/a/' => eq => 'a'); |
18
|
|
|
|
|
|
|
$tester->try('qw/a/' => ne => 'b'); |
19
|
|
|
|
|
|
|
$tester->try('qw/a/' => is => ['a']); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# Don't evaluate, but still compare: |
22
|
|
|
|
|
|
|
$tester->check(1 => is => 1); |
23
|
|
|
|
|
|
|
$tester->check(0 => isnt => 1); |
24
|
|
|
|
|
|
|
$tester->check(a => like => qr/[a-zA-Z]/); |
25
|
|
|
|
|
|
|
$tester->check(0 => unlike => qr/a-zA-Z]/); |
26
|
|
|
|
|
|
|
$tester->check(1 => '>' => 0); |
27
|
|
|
|
|
|
|
$tester->check(0 => '<' => 1); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# A failure example: |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
$tester->check([qw/a b/] => is => [qw/a b c/]); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Failed test '['a','b'] is ['a','b','c']' |
34
|
|
|
|
|
|
|
# Compared array length of $data |
35
|
|
|
|
|
|
|
# got : array with 2 element(s) |
36
|
|
|
|
|
|
|
# expect : array with 3 element(s) |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# Custom test explanation: |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
$tester->try('2 + 2' => '==' => 5, "Math is hard: %?"); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# Failed test 'Math is hard: 2 + 2 == 5' |
44
|
|
|
|
|
|
|
# got: 4 |
45
|
|
|
|
|
|
|
# expected: 5 |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 DESCRIPTION |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
See L for more information. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head1 METHODS |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head2 Test::Lazy::Tester->new( cmp_scalar => ?, cmp_structure => ?, render => ? ) |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Create a new Test::Lazy::Tester object, optionally amending the scalar comparison, structure comparison, and render subroutines |
56
|
|
|
|
|
|
|
using the supplied hashes. |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
For now, more information on customization can be gotten by: |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
perldoc -m Test::Lazy::Tester |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 $tester->check( , , , [ ] ) |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
See L for details. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head2 $tester->try( , , , [ ] ) |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
See L for details. |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head2 $tester->template() |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
Creates a C using $tester as the basis. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
See L for more details. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
Returns a new L object. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head2 $tester->render_value( ) |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Render a gotten or expected value to a form suitable for the test notice/explanation. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
This method will consult the $tester->render hash to see what if should do based on 'ref '. |
83
|
|
|
|
|
|
|
By default, ARRAY and HASH are handled by Data::Dumper using the following: |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
local $Data::Dumper::Indent = 0; |
86
|
|
|
|
|
|
|
local $Data::Dumper::Varname = 0; |
87
|
|
|
|
|
|
|
local $Data::Dumper::Terse = 1; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
An undef value is a special case, handled by the $tester->render->{undef} subroutine. |
90
|
|
|
|
|
|
|
By default, the subroutine returns the string "undef" |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head2 $tester->render_notice( , , , ) |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Render the text explantaion message. You don't need to mess with this. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=cut |
97
|
|
|
|
|
|
|
|
98
|
2
|
|
|
2
|
|
11
|
use base qw/Class::Accessor::Fast/; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
1903
|
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
__PACKAGE__->mk_accessors(qw/render cmp_scalar cmp_structure/); |
101
|
|
|
|
|
|
|
|
102
|
2
|
|
|
2
|
|
9293
|
use Data::Dumper qw/Dumper/; |
|
2
|
|
|
|
|
19645
|
|
|
2
|
|
|
|
|
174
|
|
103
|
2
|
|
|
2
|
|
20
|
use Carp; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
116
|
|
104
|
2
|
|
|
2
|
|
967
|
use Test::Deep; |
|
2
|
|
|
|
|
11202
|
|
|
2
|
|
|
|
|
502
|
|
105
|
2
|
|
|
2
|
|
17
|
use Test::Builder(); |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
409
|
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
my $deparser; |
108
|
|
|
|
|
|
|
eval { |
109
|
|
|
|
|
|
|
require B::Deparse; |
110
|
|
|
|
|
|
|
$deparser = B::Deparse->new; |
111
|
|
|
|
|
|
|
$deparser->ambient_pragmas(strict => 'all', warnings => 'all'); |
112
|
|
|
|
|
|
|
}; |
113
|
|
|
|
|
|
|
undef $deparser if $@; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
my %base_cmp_scalar = ( |
116
|
|
|
|
|
|
|
ok => sub { |
117
|
|
|
|
|
|
|
Test::More::ok($_[0], $_[2]) |
118
|
|
|
|
|
|
|
}, |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
not_ok => sub { |
121
|
|
|
|
|
|
|
Test::More::ok(! $_[0], $_[2]) |
122
|
|
|
|
|
|
|
}, |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
(map { my $mtd = $_; $_ => sub { |
125
|
|
|
|
|
|
|
Test::More::cmp_ok($_[0] => $mtd => $_[1], $_[2]) |
126
|
|
|
|
|
|
|
} } |
127
|
|
|
|
|
|
|
qw/< > <= >= lt gt le ge == != eq ne/), |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
(map { my $method = $_; $_ => sub { |
130
|
2
|
|
|
2
|
|
13
|
no strict 'refs'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
3108
|
|
131
|
|
|
|
|
|
|
"Test::More::$method"->($_[0], $_[1], $_[2]) |
132
|
|
|
|
|
|
|
} } |
133
|
|
|
|
|
|
|
qw/is isnt like unlike/), |
134
|
|
|
|
|
|
|
); |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
my %base_cmp_structure = ( |
137
|
|
|
|
|
|
|
ok => sub { |
138
|
|
|
|
|
|
|
Test::More::ok($_[0], $_[2]) |
139
|
|
|
|
|
|
|
}, |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
not_ok => sub { |
142
|
|
|
|
|
|
|
Test::More::ok(! $_[0], $_[2]) |
143
|
|
|
|
|
|
|
}, |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
(map { $_ => sub { |
146
|
|
|
|
|
|
|
Test::Deep::cmp_bag($_[0], $_[1], $_[2]); |
147
|
|
|
|
|
|
|
} } |
148
|
|
|
|
|
|
|
qw/bag same_bag samebag/), |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
(map { $_ => sub { |
151
|
|
|
|
|
|
|
Test::Deep::cmp_set($_[0], $_[1], $_[2]); |
152
|
|
|
|
|
|
|
} } |
153
|
|
|
|
|
|
|
qw/set same_set sameset/), |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
(map { $_ => sub { |
156
|
|
|
|
|
|
|
Test::Deep::cmp_deeply($_[0], $_[1], $_[2]); |
157
|
|
|
|
|
|
|
} } |
158
|
|
|
|
|
|
|
qw/same is like eq ==/), |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
(map { $_ => sub { |
161
|
|
|
|
|
|
|
Test::More::ok(!Test::Deep::eq_deeply($_[0], $_[1]), $_[2]); |
162
|
|
|
|
|
|
|
} } |
163
|
|
|
|
|
|
|
qw/isnt unlink ne !=/), |
164
|
|
|
|
|
|
|
); |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
my %base_render = ( |
167
|
|
|
|
|
|
|
ARRAY => sub { |
168
|
|
|
|
|
|
|
local $Data::Dumper::Indent = 0; |
169
|
|
|
|
|
|
|
local $Data::Dumper::Varname = 0; |
170
|
|
|
|
|
|
|
local $Data::Dumper::Terse = 1; |
171
|
|
|
|
|
|
|
my $self = shift; |
172
|
|
|
|
|
|
|
my $value = shift; |
173
|
|
|
|
|
|
|
return Dumper($value); |
174
|
|
|
|
|
|
|
}, |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
HASH => sub { |
177
|
|
|
|
|
|
|
local $Data::Dumper::Indent = 0; |
178
|
|
|
|
|
|
|
local $Data::Dumper::Varname = 0; |
179
|
|
|
|
|
|
|
local $Data::Dumper::Terse = 1; |
180
|
|
|
|
|
|
|
my $self = shift; |
181
|
|
|
|
|
|
|
my $value = shift; |
182
|
|
|
|
|
|
|
return Dumper($value); |
183
|
|
|
|
|
|
|
}, |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
undef => sub { |
186
|
|
|
|
|
|
|
return "undef"; |
187
|
|
|
|
|
|
|
}, |
188
|
|
|
|
|
|
|
); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub new { |
191
|
2
|
|
|
2
|
1
|
7
|
my $self = bless {}, shift; |
192
|
2
|
|
|
|
|
7
|
local %_ = @_; |
193
|
2
|
50
|
|
|
|
19
|
$self->{cmp_scalar} = { %base_cmp_scalar, %{ $_{cmp_scalar} || {} } }; |
|
2
|
|
|
|
|
52
|
|
194
|
2
|
50
|
|
|
|
18
|
$self->{cmp_structure} = { %base_cmp_structure, %{ $_{cmp_structure} || {} } }; |
|
2
|
|
|
|
|
39
|
|
195
|
2
|
50
|
|
|
|
10
|
$self->{render} = { %base_render, %{ $_{base_render} || {} } }; |
|
2
|
|
|
|
|
18
|
|
196
|
2
|
|
|
|
|
12
|
return $self; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub render_notice { |
200
|
114
|
|
|
114
|
1
|
13550
|
my $self = shift; |
201
|
114
|
|
|
|
|
223
|
my ($left, $compare, $right, $notice, $length) = @_; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# my $_notice = $length == 4 ? "$left $compare $right" : "$left $compare"; |
204
|
114
|
|
|
|
|
221
|
my $_notice = "$left $compare $right"; |
205
|
114
|
100
|
|
|
|
184
|
if (defined $notice) { |
206
|
70
|
50
|
|
|
|
125
|
if ($notice =~ m/%\?/) { |
207
|
0
|
|
|
|
|
0
|
$notice =~ s/%\?/$_notice/g; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
else { # Old version, deprecated. |
210
|
70
|
|
|
|
|
269
|
$notice =~ s/%(?!%)/%?/g; |
211
|
70
|
|
|
|
|
5840
|
$notice =~ s/%%/%/g; |
212
|
70
|
|
|
|
|
186
|
$notice =~ s/%\?/$_notice/g; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
else { |
216
|
44
|
|
|
|
|
56
|
$notice = $_notice; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
114
|
|
|
|
|
248
|
return $notice; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub render_value { |
223
|
136
|
|
|
136
|
1
|
158
|
my $self = shift; |
224
|
136
|
|
|
|
|
140
|
my $value = shift; |
225
|
|
|
|
|
|
|
|
226
|
136
|
|
|
|
|
148
|
my $type = ref $value; |
227
|
136
|
100
|
|
|
|
302
|
$type = "undef" unless defined $value; |
228
|
|
|
|
|
|
|
|
229
|
136
|
100
|
|
|
|
300
|
return $value unless $type; |
230
|
38
|
100
|
|
|
|
112
|
return $value unless my $renderer = $self->render->{$type}; |
231
|
34
|
|
|
|
|
208
|
return $renderer->($self, $value); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
sub _test { |
235
|
114
|
|
|
114
|
|
128
|
my $self = shift; |
236
|
114
|
|
|
|
|
163
|
my ($compare, $got, $expect, $notice) = @_; |
237
|
|
|
|
|
|
|
|
238
|
114
|
|
|
|
|
132
|
local $Test::Builder::Level = $Test::Builder::Level + 1; |
239
|
|
|
|
|
|
|
|
240
|
114
|
|
|
|
|
144
|
my $cmp = $compare; |
241
|
114
|
50
|
|
|
|
192
|
if (ref $cmp eq "CODE") { |
242
|
0
|
|
|
|
|
0
|
Test::More::ok($cmp->($got, $expect), $notice); |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
else { |
245
|
114
|
|
66
|
|
|
408
|
my $structure = ref $expect eq "ARRAY" || ref $expect eq "HASH"; |
246
|
114
|
|
|
|
|
127
|
my $scalar = ! $structure; |
247
|
|
|
|
|
|
|
|
248
|
114
|
100
|
|
|
|
343
|
my $cmp_source = $scalar ? $self->cmp_scalar : $self->cmp_structure; |
249
|
|
|
|
|
|
|
|
250
|
114
|
50
|
|
|
|
627
|
die "Don't know how to compare via ($compare)" unless $cmp = $cmp_source->{$cmp}; |
251
|
114
|
|
|
|
|
131
|
local $Test::Builder::Level = $Test::Builder::Level + 1; |
252
|
114
|
|
|
|
|
218
|
$cmp->($got, $expect, $notice); |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub check { |
257
|
22
|
|
|
22
|
1
|
27
|
my $self = shift; |
258
|
22
|
|
|
|
|
39
|
my ($got, $compare, $expect, $notice) = @_; |
259
|
22
|
|
|
|
|
26
|
my $length = @_; |
260
|
|
|
|
|
|
|
|
261
|
22
|
|
|
|
|
50
|
my $left = $self->render_value($got); |
262
|
22
|
|
|
|
|
38
|
my $right = $self->render_value($expect); |
263
|
22
|
|
|
|
|
59
|
$notice = $self->render_notice($left, $compare, $right, $notice, $length); |
264
|
|
|
|
|
|
|
|
265
|
22
|
|
|
|
|
29
|
local $Test::Builder::Level = $Test::Builder::Level + 1; |
266
|
|
|
|
|
|
|
|
267
|
22
|
|
|
|
|
48
|
return $self->_test($compare, $got, $expect, $notice); |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub try { |
271
|
92
|
|
|
92
|
1
|
453
|
my $self = shift; |
272
|
92
|
|
|
|
|
156
|
my ($statement, $compare, $expect, $notice) = @_; |
273
|
92
|
|
|
|
|
102
|
my $length = @_; |
274
|
|
|
|
|
|
|
|
275
|
92
|
50
|
|
|
|
4290
|
my @got = ref $statement eq "CODE" ? $statement->() : eval $statement; |
276
|
92
|
50
|
|
|
|
306
|
die "$statement: $@" if $@; |
277
|
92
|
|
|
|
|
97
|
my $got; |
278
|
92
|
100
|
|
|
|
162
|
if (@got > 1) { |
279
|
2
|
50
|
|
|
|
12
|
if (ref $expect eq "ARRAY") { |
|
|
50
|
|
|
|
|
|
280
|
0
|
|
|
|
|
0
|
$got = \@got; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
elsif (ref $expect eq "HASH") { |
283
|
2
|
|
|
|
|
10
|
$got = { @got }; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
else { |
286
|
0
|
|
|
|
|
0
|
$got = scalar @got; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
else { |
290
|
90
|
50
|
0
|
|
|
316
|
if (ref $expect eq "ARRAY" && (! @got || ref $got[0] ne "ARRAY")) { |
|
|
50
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
291
|
0
|
|
|
|
|
0
|
$got = \@got; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
elsif (ref $expect eq "HASH" && ! @got) { |
294
|
0
|
|
|
|
|
0
|
$got = { }; |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
else { |
297
|
90
|
|
|
|
|
127
|
$got = $got[0]; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
92
|
|
|
|
|
99
|
my $left; |
302
|
92
|
50
|
33
|
|
|
274
|
if (ref $statement eq "CODE" && $deparser) { |
303
|
0
|
|
|
|
|
0
|
my $deparse = $deparser->coderef2text($statement); |
304
|
0
|
|
|
|
|
0
|
my @deparse = split m/\n\s*/, $deparse; |
305
|
0
|
0
|
|
|
|
0
|
$deparse = join ' ', "sub", @deparse if 3 == @deparse; |
306
|
0
|
|
|
|
|
0
|
$left = $deparse; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
else { |
309
|
92
|
|
|
|
|
119
|
$left = $statement; |
310
|
|
|
|
|
|
|
} |
311
|
92
|
|
|
|
|
181
|
my $right = $self->render_value($expect); |
312
|
92
|
|
|
|
|
432
|
$notice = $self->render_notice($left, $compare, $right, $notice, $length); |
313
|
|
|
|
|
|
|
|
314
|
92
|
|
|
|
|
178
|
local $Test::Builder::Level = $Test::Builder::Level + 1; |
315
|
|
|
|
|
|
|
|
316
|
92
|
|
|
|
|
202
|
return $self->_test($compare, $got, $expect, $notice); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub template { |
320
|
1
|
|
|
1
|
1
|
2
|
my $self = shift; |
321
|
1
|
|
|
|
|
719
|
require Test::Lazy::Template; |
322
|
1
|
|
|
|
|
6
|
return Test::Lazy::Template->new($self, @_); |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
1; |