File Coverage

blib/lib/Test/Instruction.pm
Criterion Covered Total %
statement 73 124 58.8
branch 20 62 32.2
condition 1 2 50.0
subroutine 22 43 51.1
pod 3 3 100.0
total 119 234 50.8


line stmt bran cond sub pod time code
1             package Test::Instruction;
2              
3 4     4   55359 use 5.006; use strict; use warnings; our $VERSION = '0.02';
  4     4   25  
  4     4   16  
  4         6  
  4         123  
  4         18  
  4         6  
  4         167  
4 4     4   1452 use Compiled::Params::OO qw/cpo/;
  4         429026  
  4         37  
5 4     4   352 use Types::Standard qw/Optional Str Int Bool Any CodeRef ArrayRef HashRef/;
  4         6  
  4         26  
6 4     4   4690 use B qw/svref_2object/;
  4         8  
  4         169  
7 4     4   1470 use Switch::Again qw/switch/;
  4         12865  
  4         26  
8 4     4   1760 use Test::More;
  4         155882  
  4         32  
9 4     4   896 use base 'Import::Export';
  4         8  
  4         1242  
10              
11             our (%EX, $validate);
12             BEGIN {
13 4     4   34 %EX = (
14             instruction => [qw/all/],
15             instructions => [qw/all/],
16             finish => [qw/all/]
17             );
18 4         26 $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 14     14 1 3229 my $instruction = $validate->instruction->(@_);
48 14         548 my ($test_name, @test) = ("", ());
49 14 50       36 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 14         26 @test = _run_the_code( $instruction );
56 14         57 $test_name = shift @test;
57             }
58              
59 14 50       37 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   383 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 3 50   3   1222 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 1     1   470 return isa_ok(
278             $test[0],
279             $instruction->expected,
280             sprintf "%s isa_ok - %s",
281             $test_name,
282             $instruction->expected
283             );
284             },
285             like => sub {
286 1     1   411 my $like = $instruction->expected;
287 1         13 return like(
288             $test[0],
289             qr/$like/,
290             sprintf "%s is like - %s",
291             $test_name,
292             $instruction->expected
293             );
294             },
295             true => sub {
296 3     3   1346 return ok($test[0], "${test_name} is true - 1");
297             },
298             false => sub {
299 3     3   1306 return ok(!$test[0], "${test_name} is false - 0");
300             },
301             undef => sub {
302 0     0   0 return is($test[0], undef, "${test_name} is undef");
303             },
304             ok => sub {
305 2     2   968 return ok(@test, "${test_name} is ok");
306             },
307             skip => sub {
308 0     0   0 return ok(1, "${test_name} - skip");
309             },
310             default => sub {
311 0     0   0 ok(0, "Unknown instruction $_[0]: passed to instrcution");
312 0         0 return;
313 14         399 };
314             }
315              
316             sub instructions {
317 2     2 1 100 my $instructions = $validate->instructions->(@_);
318              
319 2         80 ok(1, sprintf "instructions: %s", $instructions->name);
320              
321 2 100       715 my $instance = $instructions->build ? _build($instructions->build) : $instructions->instance;
322              
323 2         27 my %test_info = (
324             fail => 0,
325             tested => 0,
326             );
327              
328 2         4 for my $instruction (@{$instructions->run}) {
  2         7  
329 5         1179 $test_info{tested}++;
330 5 100       13 if (my $subtests = delete $instruction->{instructions}) {
331             my ($test_name, $new_instance) = _run_the_code(
332             $validate->instruction->(
333             instance => $instance,
334 1         3 %{$instruction}
  1         6  
335             )
336             );
337            
338             $test_info{fail}++
339             unless instruction(
340             instance => $new_instance,
341             test => $instruction->{test},
342             expected => $instruction->{expected}
343 1 50       10 );
344              
345 1         314 instructions(
346             instance => $new_instance,
347             run => $subtests,
348             name => sprintf "Subtest -> %s -> %s", $instructions->name, $test_name
349             );
350 1         249 next;
351             }
352              
353             $test_info{fail}++
354             unless instruction(
355             instance => $instance,
356 4 50       6 %{$instruction}
  4         13  
357             );
358             }
359            
360 2 50       479 $test_info{ok} = $test_info{fail} ? 0 : 1;
361             return ok(
362             $test_info{ok},
363             sprintf(
364             "instructions: %s - tested %d instructions - success: %d - failure: %d",
365             $instructions->name,
366             $test_info{tested},
367             ($test_info{tested} - $test_info{fail}),
368             $test_info{fail}
369             )
370 2         16 );
371             }
372              
373             sub finish {
374 3     3 1 816 my $done_testing = done_testing(shift);
375 3         2175 return $done_testing;
376             }
377              
378              
379             sub _build {
380 1     1   6 my $build = $validate->build->(@_);
381 1   50     37 my $new = $build->new || 'new';
382 1 50       10 return $build->class->$new($build->args_list ? @{ $build->args } : $build->args);
  0         0  
383             }
384              
385             sub _run_the_code {
386 15     15   52 my $instruction = shift;
387 15 100       54 if ($instruction->meth) {
    100          
    50          
388 6         16 my $meth = $instruction->meth;
389             return (
390             "function: ${meth}",
391             $instruction->instance->$meth(
392             $instruction->args_list
393 6 50       46 ? @{ $instruction->args }
  0         0  
394             : $instruction->args
395             )
396             );
397             } elsif ($instruction->func) {
398 5         29 my $func_name = svref_2object($instruction->func)->GV->NAME;
399             return (
400             "function: ${func_name}",
401 5 100       23 $instruction->func->($instruction->args_list ? @{$instruction->args} : $instruction->args)
  2         7  
402             );
403             } elsif ($instruction->instance) {
404 4         13 return ('instance', $instruction->instance);
405             }
406              
407             die(
408 0           'instruction passed to _run_the_code must have a func, meth or instance key'
409             );
410             }
411              
412             __END__