File Coverage

blib/lib/Test/Instruction.pm
Criterion Covered Total %
statement 75 127 59.0
branch 21 64 32.8
condition 1 2 50.0
subroutine 24 45 53.3
pod 3 3 100.0
total 124 241 51.4


line stmt bran cond sub pod time code
1             package Test::Instruction;
2              
3 5     5   73059 use 5.006; use strict; use warnings; our $VERSION = '0.03';
  5     5   43  
  5     5   44  
  5         16  
  5         156  
  5         29  
  5         10  
  5         277  
4 5     5   2378 use Compiled::Params::OO qw/cpo/;
  5         750707  
  5         56  
5 5     5   605 use Types::Standard qw/Optional Str Int Bool Any CodeRef ArrayRef HashRef/;
  5         13  
  5         43  
6 5     5   12786 use B qw/svref_2object/;
  5         18  
  5         289  
7 5     5   2369 use Switch::Again qw/switch/;
  5         20630  
  5         48  
8 5     5   3186 use Test::More;
  5         274788  
  5         48  
9 5     5   1418 use base 'Import::Export';
  5         11  
  5         1918  
10              
11             our (%EX, $validate);
12             BEGIN {
13 5     5   63 %EX = (
14             instruction => [qw/all/],
15             instructions => [qw/all/],
16             finish => [qw/all/]
17             );
18 5         46 $validate = cpo(
19             instruction => {
20             instance => Optional->of(Any),
21             meth => Optional->of(Str),
22             func => Optional->of(CodeRef),
23             args => Optional->of(Any),
24             args_list => Optional->of(Bool),
25             test => Optional->of(Str),
26             expected => Optional->of(Any),
27             catch => Optional->of(Bool),
28             key => Optional->of(Str),
29             index => Optional->of(Int),
30             },
31             instructions => {
32             name => Str,
33             run => ArrayRef,
34             build => Optional->of(HashRef),
35             instance => Optional->of(Any)
36             },
37             build => {
38             class => Str,
39             new => Optional->of(Str),
40             args => Optional->of(Any),
41             args_list => Optional->of(Bool)
42             }
43             );
44             }
45              
46             sub instruction {
47 20     20 1 8227 my $instruction = $validate->instruction->(@_);
48 20         1043 my ($test_name, @test) = ("", ());
49 20 50       65 if ( $instruction->catch ) {
50 0         0 $test_name = 'catch';
51 0 0       0 exits $instruction->test or $instruction->test('like');
52 0         0 eval { _run_the_code( $instruction ) };
  0         0  
53 0         0 @test = $@;
54             } else {
55 20         49 @test = _run_the_code( $instruction );
56 20         113 $test_name = shift @test;
57             }
58              
59 20 50       66 if ( not $instruction->test ) {
60 0         0 ok(0, "No 'test' passed with instruction");
61 0         0 return;
62             }
63              
64             switch $instruction->test,
65             "ref" => sub {
66 0     0   0 return is_deeply( $test[0], $instruction->expected, "${test_name} is ref - is_deeply" );
67              
68             },
69             ref_key_scalar => sub {
70 0 0   0   0 return ok(0, "No key passed to test - ref_key_scalar - testing - ${test_name}")
71             if (! $instruction->key );
72             return is(
73 0         0 $test[0]->{$instruction->key},
74             $instruction->expected,
75             sprintf "%s is ref - has scalar key: %s - is - %s",
76             $test_name,
77             $instruction->key,
78             $instruction->expected
79             );
80             },
81             ref_key_like => sub {
82 0 0   0   0 return ok(0, "No key passed to test - ref_key_like - testing - ${test_name}")
83             if (! $instruction->key );
84 0         0 my $like = $instruction->expected;
85             return like(
86 0         0 $test[0]->{$instruction->key},
87             qr/$like/,
88             sprintf "%s is ref - has scalar key: %s - like - %s",
89             $test_name,
90             $instruction->key,
91             $instruction->expected
92             );
93             },
94             ref_key_ref => sub {
95 0 0   0   0 return ok(0, "No key passed to test - ref_key_ref - testing - ${test_name}")
96             if (! $instruction->key );
97             return is_deeply(
98 0         0 $test[0]->{$instruction->key},
99             $instruction->expected,
100             sprintf "%s is ref - has ref key: %s - is_deeply - ref",
101             $test_name,
102             $instruction->key,
103             );
104             },
105             ref_index_scalar => sub {
106 0 0   0   0 return ok(0, "No index passed to test - ref_index_scalar - testing - ${test_name}")
107             if (! defined $instruction->index );
108 0         0 return is(
109             $test[0]->[$instruction->index],
110             $instruction->expected,
111             sprintf "%s is ref - has scalar index: %s - is - %s",
112             $test_name,
113             $instruction->index,
114             $instruction->expected
115             );
116             },
117             ref_index_ref => sub {
118 0 0   0   0 return ok(0, "No index passed to test - ref_index_ref - testing - ${test_name}")
119             if (! defined $instruction->index );
120 0         0 is_deeply(
121             $test[0]->[$instruction->index],
122             $instruction->expected,
123             sprintf "%s is ref - has ref index: %s - is_deeply - ref",
124             $test_name,
125             $instruction->index,
126             );
127             },
128             ref_index_like => sub {
129 0 0   0   0 return ok(0, "No index passed to test - ref_index_like - testing - ${test_name}")
130             if (! defined $instruction->index );
131 0         0 my $like = $instruction->expected;
132 0         0 return like(
133             $test[0]->[$instruction->index],
134             qr/$like/,
135             sprintf "%s is ref - has scalar index: %s - like - %s",
136             $test_name,
137             $instruction->index,
138             $instruction->expected
139             );
140             },
141             ref_index_obj => sub {
142 0 0   0   0 return ok(0, "No index passed to test - ref_index_obj - testing - ${test_name}")
143             if (! defined $instruction->index );
144 0         0 return isa_ok(
145             $test[0]->[$instruction->index],
146             $instruction->expected,
147             sprintf "%s is ref - has obj index: %s - isa_ok - %s",
148             $test_name,
149             $instruction->index,
150             $instruction->expected
151             );
152             },
153             list_index_scalar => sub {
154 0 0   0   0 return ok(0, "No index passed to test - list_index_scalar - testing - ${test_name}")
155             if (! defined $instruction->index );
156              
157 0         0 return is(
158             $test[$instruction->index],
159             $instruction->expected,
160             sprintf "%s is list - has scalar index: %s - is - %s",
161             $test_name,
162             $instruction->index,
163             $instruction->expected
164             );
165             },
166             list_index_ref => sub {
167 0 0   0   0 return ok(0, "No index passed to test - list_index_ref - testing - ${test_name}")
168             if (! defined $instruction->index );
169 0         0 return is_deeply(
170             $test[$instruction->index],
171             $instruction->expected,
172             sprintf "%s is list - has ref index: %s - is_deeply - ref",
173             $test_name,
174             $instruction->index,
175             );
176             },
177             list_index_like => sub {
178 0 0   0   0 return ok(0, "No index passed to test - list_index_like - testing - ${test_name}")
179             if (! defined $instruction->index );
180 0         0 my $like = $instruction->expected;
181 0         0 return is(
182             $test[$instruction->index],
183             qr/$like/,
184             sprintf "%s is list - has scalar index: %s - like - %s",
185             $test_name,
186             $instruction->index,
187             $instruction->expected
188             );
189             },
190             list_index_obj => sub {
191 0 0   0   0 return ok(0, "No index passed to test - list_index_obj - testing - ${test_name}")
192             if (! defined $instruction->index );
193 0         0 return isa_ok(
194             $test[$instruction->index],
195             $instruction->expected,
196             sprintf "%s is list - has obj index: %s - isa_ok - %s",
197             $test_name,
198             $instruction->index,
199             $instruction->expected
200             ),
201             },
202             list_key_scalar => sub {
203 0 0   0   0 return ok(0, "No key passed to test - list_key_scalar - testing - ${test_name}")
204             if (! $instruction->key );
205             return is(
206 0         0 {@test}->{$instruction->key},
207             $instruction->expected,
208             sprintf "%s is list - has scalar key: %s - is - %s",
209             $test_name,
210             $instruction->key,
211             $instruction->expected
212             );
213             },
214             list_key_ref => sub {
215 0 0   0   0 return ok(0, "No key passed to test - list_key_ref - testing - ${test_name}")
216             if (! $instruction->key );
217             return is_deeply(
218 0         0 {@test}->{$instruction->key},
219             $instruction->expected,
220             sprintf "%s is list - has ref key: %s - is_deeply - ref",
221             $test_name,
222             $instruction->key,
223             );
224             },
225             list_key_like => sub {
226 0 0   0   0 return ok(0, "No key passed to test - list_key_like - testing - ${test_name}")
227             if (! $instruction->key );
228 0         0 my $like = $instruction->expected;
229             return is(
230 0         0 {@test}->{$instruction->key},
231             qr/$like/,
232             sprintf "%s is list - has scalar key: %s - like - %s",
233             $test_name,
234             $instruction->key,
235             $instruction->expected
236             );
237             },
238             count => sub {
239 0     0   0 return is(
240             scalar @test,
241             $instruction->expected,
242             sprintf "%s is array - count - is - %s",
243             $test_name,
244             $instruction->expected
245             );
246             },
247             count_ref => sub {
248             return is(
249 0     0   0 scalar @{$test[0]},
  0         0  
250             $instruction->expected,
251             sprintf "%s is ref - count - is - %s",
252             $test_name,
253             $instruction->expected
254             );
255             },
256             scalar => sub {
257 1 50   1   487 return is( $test[0], $instruction->expected, sprintf "%s is scalar - is - %s",
258             $test_name, defined $instruction->expected ? $instruction->expected : 'undef');
259             },
260             hash => sub {
261 4 50   4   2130 return is_deeply(
262             scalar @test == 1 ? $test[0] : {@test},
263             $instruction->expected,
264             sprintf "%s is hash - is_deeply",
265             $test_name,
266             );
267             },
268             array => sub {
269 0 0   0   0 return is_deeply(
270             scalar @test == 1 ? $test[0] : \@test,
271             $instruction->expected,
272             sprintf "%s is array - is_deeply",
273             $test_name,
274             );
275             },
276             obj => sub {
277 2     2   1179 return isa_ok(
278             $test[0],
279             $instruction->expected,
280             sprintf "%s isa_ok - %s",
281             $test_name,
282             $instruction->expected
283             );
284             },
285             code => sub {
286 2     2   1052 return is(
287             ref $test[0],
288             'CODE',
289             sprintf "%s is a CODE block",
290             $test_name
291             );
292             },
293             code_execute => sub {
294             return is_deeply(
295 2 50   2   1138 $test[0]->($instruction->args ? @{$instruction->args} : ()),
  0         0  
296             $instruction->expected,
297             sprintf "%s is deeply %s",
298             $test_name,
299             $instruction->expected
300             );
301             },
302             like => sub {
303 1     1   546 my $like = $instruction->expected;
304 1         18 return like(
305             $test[0],
306             qr/$like/,
307             sprintf "%s is like - %s",
308             $test_name,
309             $instruction->expected
310             );
311             },
312             true => sub {
313 3     3   1708 return ok($test[0], "${test_name} is true - 1");
314             },
315             false => sub {
316 3     3   1772 return ok(!$test[0], "${test_name} is false - 0");
317             },
318             undef => sub {
319 0     0   0 return is($test[0], undef, "${test_name} is undef");
320             },
321             ok => sub {
322 2     2   1309 return ok(@test, "${test_name} is ok");
323             },
324             skip => sub {
325 0     0   0 return ok(1, "${test_name} - skip");
326             },
327             default => sub {
328 0     0   0 ok(0, "Unknown instruction $_[0]: passed to instrcution");
329 0         0 return;
330 20         699 };
331             }
332              
333             sub instructions {
334 2     2 1 118 my $instructions = $validate->instructions->(@_);
335              
336 2         124 ok(1, sprintf "instructions: %s", $instructions->name);
337              
338 2 100       796 my $instance = $instructions->build ? _build($instructions->build) : $instructions->instance;
339              
340 2         34 my %test_info = (
341             fail => 0,
342             tested => 0,
343             );
344              
345 2         7 for my $instruction (@{$instructions->run}) {
  2         8  
346 5         1616 $test_info{tested}++;
347 5 100       18 if (my $subtests = delete $instruction->{instructions}) {
348             my ($test_name, $new_instance) = _run_the_code(
349             $validate->instruction->(
350             instance => $instance,
351 1         5 %{$instruction}
  1         7  
352             )
353             );
354            
355             $test_info{fail}++
356             unless instruction(
357             instance => $new_instance,
358             test => $instruction->{test},
359             expected => $instruction->{expected}
360 1 50       23 );
361              
362 1         428 instructions(
363             instance => $new_instance,
364             run => $subtests,
365             name => sprintf "Subtest -> %s -> %s", $instructions->name, $test_name
366             );
367 1         298 next;
368             }
369              
370             $test_info{fail}++
371             unless instruction(
372             instance => $instance,
373 4 50       6 %{$instruction}
  4         17  
374             );
375             }
376            
377 2 50       631 $test_info{ok} = $test_info{fail} ? 0 : 1;
378             return ok(
379             $test_info{ok},
380             sprintf(
381             "instructions: %s - tested %d instructions - success: %d - failure: %d",
382             $instructions->name,
383             $test_info{tested},
384             ($test_info{tested} - $test_info{fail}),
385             $test_info{fail}
386             )
387 2         26 );
388             }
389              
390             sub finish {
391 4     4 1 1820 my $done_testing = done_testing(shift);
392 4         4044 return $done_testing;
393             }
394              
395              
396             sub _build {
397 1     1   7 my $build = $validate->build->(@_);
398 1   50     49 my $new = $build->new || 'new';
399 1 50       20 return $build->class->$new($build->args_list ? @{ $build->args } : $build->args);
  0         0  
400             }
401              
402             sub _run_the_code {
403 21     21   80 my $instruction = shift;
404 21 100       150 if ($instruction->meth) {
    100          
    50          
405 11         37 my $meth = $instruction->meth;
406             return (
407             "function: ${meth}",
408             $instruction->instance->$meth(
409             $instruction->args_list
410 11 50       113 ? @{ $instruction->args }
  0         0  
411             : $instruction->args
412             )
413             );
414             } elsif ($instruction->func) {
415 5         37 my $func_name = svref_2object($instruction->func)->GV->NAME;
416             return (
417             "function: ${func_name}",
418 5 100       31 $instruction->func->($instruction->args_list ? @{$instruction->args} : $instruction->args)
  2         7  
419             );
420             } elsif ($instruction->instance) {
421 5         22 return ('instance', $instruction->instance);
422             }
423              
424             die(
425 0           'instruction passed to _run_the_code must have a func, meth or instance key'
426             );
427             }
428              
429             __END__