blib/lib/Moonshine/Test.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 143 | 149 | 95.9 |
branch | 49 | 60 | 81.6 |
condition | 2 | 4 | 50.0 |
subroutine | 16 | 16 | 100.0 |
pod | 4 | 4 | 100.0 |
total | 214 | 233 | 91.8 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package Moonshine::Test; | ||||||
2 | |||||||
3 | 7 | 7 | 373435 | use strict; | |||
7 | 53 | ||||||
7 | 161 | ||||||
4 | 7 | 7 | 28 | use warnings; | |||
7 | 11 | ||||||
7 | 137 | ||||||
5 | 7 | 7 | 2979 | use Test::More; | |||
7 | 28857 | ||||||
7 | 39 | ||||||
6 | 7 | 7 | 1745 | use Scalar::Util qw/blessed/; | |||
7 | 9 | ||||||
7 | 257 | ||||||
7 | 7 | 7 | 3113 | use Params::Validate qw/:all/; | |||
7 | 51462 | ||||||
7 | 1079 | ||||||
8 | 7 | 7 | 45 | use B qw/svref_2object/; | |||
7 | 12 | ||||||
7 | 264 | ||||||
9 | 7 | 7 | 32 | use Exporter 'import'; | |||
7 | 11 | ||||||
7 | 145 | ||||||
10 | 7 | 7 | 2940 | use Acme::AsciiEmoji; | |||
7 | 41079 | ||||||
7 | 53 | ||||||
11 | |||||||
12 | our @EMO = @Acme::AsciiEmoji::EXPORT_OK; | ||||||
13 | our @EXPORT = qw/render_me moon_test moon_test_one sunrise/; | ||||||
14 | our @EXPORT_OK = (qw/render_me moon_test moon_test_one sunrise/, @EMO); | ||||||
15 | our %EXPORT_TAGS = ( | ||||||
16 | all => [qw/render_me moon_test moon_test_one sunrise/, @EMO], | ||||||
17 | element => [qw/render_me sunrise/], | ||||||
18 | emo => [@EMO], | ||||||
19 | ); | ||||||
20 | |||||||
21 | 7 | 7 | 38443 | use feature qw/switch/; | |||
7 | 14 | ||||||
7 | 758 | ||||||
22 | 7 | 7 | 3941 | no if $] >= 5.017011, warnings => 'experimental::smartmatch'; | |||
7 | 94 | ||||||
7 | 39 | ||||||
23 | |||||||
24 | =head1 NAME | ||||||
25 | |||||||
26 | Moonshine::Test - Test! | ||||||
27 | |||||||
28 | =head1 VERSION | ||||||
29 | |||||||
30 | Version 0.16 | ||||||
31 | |||||||
32 | =cut | ||||||
33 | |||||||
34 | our $VERSION = '0.16'; | ||||||
35 | |||||||
36 | =head1 SYNOPSIS | ||||||
37 | |||||||
38 | use Moonshine::Test qw/:all/; | ||||||
39 | |||||||
40 | moon_test_one( | ||||||
41 | test => 'scalar', | ||||||
42 | meth => \&Moonshine::Util::append_str, | ||||||
43 | args => [ | ||||||
44 | 'first', 'second' | ||||||
45 | ], | ||||||
46 | args_list => 1, | ||||||
47 | expected => 'first second', | ||||||
48 | ); | ||||||
49 | |||||||
50 | sunrise(1); | ||||||
51 | |||||||
52 | =head1 EXPORT | ||||||
53 | |||||||
54 | =head2 all | ||||||
55 | |||||||
56 | =over | ||||||
57 | |||||||
58 | =item moon_test | ||||||
59 | |||||||
60 | =item moon_test_one | ||||||
61 | |||||||
62 | =item render_me | ||||||
63 | |||||||
64 | =item done_testing | ||||||
65 | |||||||
66 | =back | ||||||
67 | |||||||
68 | =head2 element | ||||||
69 | |||||||
70 | =over | ||||||
71 | |||||||
72 | =item render_me | ||||||
73 | |||||||
74 | =item done_testing | ||||||
75 | |||||||
76 | =back | ||||||
77 | |||||||
78 | =head1 SUBROUTINES/METHODS | ||||||
79 | |||||||
80 | =head2 moon_test_one | ||||||
81 | |||||||
82 | moon_test_one( | ||||||
83 | test => 'render_me', | ||||||
84 | instance => Moonshine::Component->new(), | ||||||
85 | func => 'button', | ||||||
86 | args => { | ||||||
87 | data => '...' | ||||||
88 | }, | ||||||
89 | expected => '', | ||||||
90 | ); | ||||||
91 | |||||||
92 | =head2 Instructions | ||||||
93 | |||||||
94 | Valid instructions moon_test_one accepts | ||||||
95 | |||||||
96 | =head3 test/expected | ||||||
97 | |||||||
98 | test => 'like' | ||||||
99 | expected => 'a horrible death' | ||||||
100 | .... | ||||||
101 | like($test_outcome, qr/$expected/, "function: $func is like - $expected"); | ||||||
102 | |||||||
103 | moon_test_one can currently run the following tests. | ||||||
104 | |||||||
105 | =over | ||||||
106 | |||||||
107 | =item ok - ok - a true value | ||||||
108 | |||||||
109 | =item ref - is_deeply - expected [] or {} | ||||||
110 | |||||||
111 | =item scalar - is - expected '', | ||||||
112 | |||||||
113 | =item hash - is_deeply - expected {}, | ||||||
114 | |||||||
115 | =item array - is_deeply - expected [], | ||||||
116 | |||||||
117 | =item obj - isa_ok - expected '', | ||||||
118 | |||||||
119 | =item like - like - '', | ||||||
120 | |||||||
121 | =item true - is - 1, | ||||||
122 | |||||||
123 | =item false - is - 0, | ||||||
124 | |||||||
125 | =item undef - is - undef | ||||||
126 | |||||||
127 | =item ref_key_scalar - is - '' (requires key) | ||||||
128 | |||||||
129 | =item ref_key_ref - is_deeply - [] or {} (requires key) | ||||||
130 | |||||||
131 | =item ref_key_like - like - '' | ||||||
132 | |||||||
133 | =item ref_index_scalar - is - '' (requires index) | ||||||
134 | |||||||
135 | =item ref_index_ref - is_deeply - [] or {} (required index) | ||||||
136 | |||||||
137 | =item ref_index_like - like - '' | ||||||
138 | |||||||
139 | =item ref_index_obj - isa_ok - '' | ||||||
140 | |||||||
141 | =item list_key_scalar - is - '' (requires key) | ||||||
142 | |||||||
143 | =item list_key_ref - is_deeply - [] or {} (requires key) | ||||||
144 | |||||||
145 | =item list_key_like - like - '' | ||||||
146 | |||||||
147 | =item list_index_scalar - is - '' (requires index) | ||||||
148 | |||||||
149 | =item list_index_ref - is_deeply - [] or {} (required index) | ||||||
150 | |||||||
151 | =item list_index_obj - isa_ok - '' | ||||||
152 | |||||||
153 | =item list_index_like - like - '' | ||||||
154 | |||||||
155 | =item count - is - '' | ||||||
156 | |||||||
157 | =item count_ref - is - '' | ||||||
158 | |||||||
159 | =item skip - ok(1) | ||||||
160 | |||||||
161 | =back | ||||||
162 | |||||||
163 | =head3 catch | ||||||
164 | |||||||
165 | when you want to catch exceptions.... | ||||||
166 | |||||||
167 | catch => 1, | ||||||
168 | |||||||
169 | defaults the instruction{test} to like. | ||||||
170 | |||||||
171 | =head3 instance | ||||||
172 | |||||||
173 | my $instance = Moonshine::Element->new(); | ||||||
174 | instance => $instance, | ||||||
175 | |||||||
176 | =head3 func | ||||||
177 | |||||||
178 | call a function from the instance | ||||||
179 | |||||||
180 | instance => $instance, | ||||||
181 | func => 'render' | ||||||
182 | |||||||
183 | =head3 meth | ||||||
184 | |||||||
185 | meth => \&Moonshine::Element::render, | ||||||
186 | |||||||
187 | =head3 args | ||||||
188 | |||||||
189 | {} or [] | ||||||
190 | |||||||
191 | =head3 args_list | ||||||
192 | |||||||
193 | args => [qw/one, two/], | ||||||
194 | args_list => 1, | ||||||
195 | |||||||
196 | =head3 index | ||||||
197 | |||||||
198 | index - required when testing - ref_index_* | ||||||
199 | |||||||
200 | =head3 key | ||||||
201 | |||||||
202 | key - required when testing - ref_key_* | ||||||
203 | |||||||
204 | =cut | ||||||
205 | |||||||
206 | sub moon_test_one { | ||||||
207 | 86 | 86 | 1 | 116836 | my %instruction = validate_with( | ||
208 | params => \@_, | ||||||
209 | spec => { | ||||||
210 | instance => 0, | ||||||
211 | meth => 0, | ||||||
212 | func => 0, | ||||||
213 | args => { default => {} }, | ||||||
214 | args_list => 0, | ||||||
215 | test => 0, | ||||||
216 | expected => 0, | ||||||
217 | catch => 0, | ||||||
218 | key => 0, | ||||||
219 | index => 0, | ||||||
220 | built => 0, | ||||||
221 | } | ||||||
222 | ); | ||||||
223 | |||||||
224 | 86 | 541 | my @test = (); | ||||
225 | 86 | 140 | my $test_name = ''; | ||||
226 | 86 | 152 | my @expected = $instruction{expected}; | ||||
227 | |||||||
228 | 86 | 100 | 180 | if ( $instruction{catch} ) { | |||
229 | 3 | 7 | $test_name = 'catch'; | ||||
230 | 3 | 50 | 14 | exists $instruction{test} or $instruction{test} = 'like'; | |||
231 | 3 | 5 | eval { _run_the_code( \%instruction ) }; | ||||
3 | 8 | ||||||
232 | 3 | 132 | @test = $@; | ||||
233 | } | ||||||
234 | else { | ||||||
235 | 83 | 187 | @test = _run_the_code( \%instruction ); | ||||
236 | 83 | 4767 | $test_name = shift @test; | ||||
237 | } | ||||||
238 | |||||||
239 | 86 | 100 | 216 | if ( not exists $instruction{test} ) { | |||
240 | 1 | 6 | ok(0); | ||||
241 | 1 | 510 | diag 'No instruction{test} passed to moon_test_one'; | ||||
242 | 1 | 169 | return; | ||||
243 | } | ||||||
244 | |||||||
245 | 85 | 124 | given ( $instruction{test} ) { | ||||
246 | 85 | 199 | when ('ref') { | ||||
247 | 6 | 28 | return is_deeply( $test[0], $expected[0], | ||||
248 | "$test_name is ref - is_deeply" ); | ||||||
249 | } | ||||||
250 | 79 | 104 | when ('ref_key_scalar') { | ||||
251 | return exists $instruction{key} | ||||||
252 | ? is( | ||||||
253 | $test[0]->{ $instruction{key} }, | ||||||
254 | 3 | 100 | 23 | $expected[0], | |||
255 | "$test_name is ref - has scalar key: $instruction{key} - is - $expected[0]" | ||||||
256 | ) | ||||||
257 | : ok( | ||||||
258 | 0, | ||||||
259 | "No key passed to test - ref_key_scalar - testing - $test_name" | ||||||
260 | ); | ||||||
261 | } | ||||||
262 | 76 | 128 | when ('ref_key_like') { | ||||
263 | return exists $instruction{key} | ||||||
264 | ? like( | ||||||
265 | $test[0]->{ $instruction{key} }, | ||||||
266 | 3 | 100 | 51 | qr/$expected[0]/, | |||
267 | "$test_name is ref - has scalar key: $instruction{key} - like - $expected[0]" | ||||||
268 | ) | ||||||
269 | : ok( 0, | ||||||
270 | "No key passed to test - ref_key_like - testing - $test_name" ); | ||||||
271 | } | ||||||
272 | 73 | 101 | when ('ref_key_ref') { | ||||
273 | return exists $instruction{key} | ||||||
274 | ? is_deeply( | ||||||
275 | $test[0]->{ $instruction{key} }, | ||||||
276 | 5 | 100 | 31 | $expected[0], | |||
277 | "$test_name is ref - has ref key: $instruction{key} - is_deeply - ref" | ||||||
278 | ) | ||||||
279 | : ok( 0, | ||||||
280 | "No key passed to test - ref_key_ref - testing - $test_name" ); | ||||||
281 | } | ||||||
282 | 68 | 92 | when ('ref_index_scalar') { | ||||
283 | return exists $instruction{index} | ||||||
284 | ? is( | ||||||
285 | 6 | 100 | 37 | $test[0]->[ $instruction{index} ], | |||
286 | $expected[0], | ||||||
287 | "$test_name is ref - has scalar index: $instruction{index} - is - $expected[0]" | ||||||
288 | ) | ||||||
289 | : ok( | ||||||
290 | 0, | ||||||
291 | "No index passed to test - ref_index_scalar - testing - $test_name" | ||||||
292 | ); | ||||||
293 | } | ||||||
294 | 62 | 77 | when ('ref_index_ref') { | ||||
295 | return exists $instruction{index} | ||||||
296 | ? is_deeply( | ||||||
297 | 3 | 100 | 22 | $test[0]->[ $instruction{index} ], | |||
298 | $expected[0], | ||||||
299 | "$test_name is ref - has ref index: $instruction{index} - is_deeply - ref" | ||||||
300 | ) | ||||||
301 | : ok( | ||||||
302 | 0, | ||||||
303 | "No index passed to test - ref_index_ref - testing - $test_name" | ||||||
304 | ); | ||||||
305 | } | ||||||
306 | 59 | 70 | when ('ref_index_like') { | ||||
307 | return exists $instruction{index} | ||||||
308 | ? like( | ||||||
309 | 3 | 100 | 42 | $test[0]->[ $instruction{index} ], | |||
310 | qr/$expected[0]/, | ||||||
311 | "$test_name is ref - has scalar index: $instruction{index} - like - $expected[0]" | ||||||
312 | ) | ||||||
313 | : ok( | ||||||
314 | 0, | ||||||
315 | "No index passed to test - ref_index_like - testing - $test_name" | ||||||
316 | ); | ||||||
317 | } | ||||||
318 | 56 | 72 | when ('ref_index_obj') { | ||||
319 | return exists $instruction{index} | ||||||
320 | ? isa_ok( | ||||||
321 | 1 | 50 | 9 | $test[0]->[ $instruction{index} ], | |||
322 | $expected[0], | ||||||
323 | "$test_name is ref - has obj index: $instruction{index} - isa_ok - $expected[0]" | ||||||
324 | ) | ||||||
325 | : ok( | ||||||
326 | 0, | ||||||
327 | "No index passed to test - ref_index_obj - testing - $test_name" | ||||||
328 | ); | ||||||
329 | } | ||||||
330 | 55 | 71 | when ('list_index_scalar') { | ||||
331 | return exists $instruction{index} | ||||||
332 | ? is( | ||||||
333 | 3 | 100 | 23 | $test[ $instruction{index} ], | |||
334 | $expected[0], | ||||||
335 | "$test_name is list - has scalar index: $instruction{index} - is - $expected[0]" | ||||||
336 | ) | ||||||
337 | : ok( | ||||||
338 | 0, | ||||||
339 | "No index passed to test - list_index_scalar - testing - $test_name" | ||||||
340 | ); | ||||||
341 | } | ||||||
342 | 52 | 69 | when ('list_index_ref') { | ||||
343 | return exists $instruction{index} | ||||||
344 | ? is_deeply( | ||||||
345 | 3 | 100 | 26 | $test[ $instruction{index} ], | |||
346 | $expected[0], | ||||||
347 | "$test_name is list - has ref index: $instruction{index} - is_deeply - ref" | ||||||
348 | ) | ||||||
349 | : ok( | ||||||
350 | 0, | ||||||
351 | "No index passed to test - list_index_ref - testing - $test_name" | ||||||
352 | ); | ||||||
353 | } | ||||||
354 | 49 | 60 | when ('list_index_like') { | ||||
355 | return exists $instruction{index} | ||||||
356 | ? like( | ||||||
357 | 3 | 100 | 44 | $test[ $instruction{index} ], | |||
358 | qr/$expected[0]/, | ||||||
359 | "$test_name is list - has scalar index: $instruction{index} - like - $expected[0]" | ||||||
360 | ) | ||||||
361 | : ok( | ||||||
362 | 0, | ||||||
363 | "No index passed to test - list_index_like - testing - $test_name" | ||||||
364 | ); | ||||||
365 | } | ||||||
366 | 46 | 63 | when ('list_index_obj') { | ||||
367 | return exists $instruction{index} | ||||||
368 | ? isa_ok( | ||||||
369 | 1 | 50 | 9 | $test[ $instruction{index} ], | |||
370 | $expected[0], | ||||||
371 | "$test_name is list - has obj index: $instruction{index} - isa_ok - $expected[0]" | ||||||
372 | ) | ||||||
373 | : ok( | ||||||
374 | 0, | ||||||
375 | "No index passed to test - list_index_obj - testing - $test_name" | ||||||
376 | ); | ||||||
377 | } | ||||||
378 | 45 | 59 | when ('list_key_scalar') { | ||||
379 | return exists $instruction{key} | ||||||
380 | ? is( | ||||||
381 | {@test}->{ $instruction{key} }, | ||||||
382 | 3 | 100 | 23 | $expected[0], | |||
383 | "$test_name is list - has scalar key: $instruction{key} - is - $expected[0]" | ||||||
384 | ) | ||||||
385 | : ok( | ||||||
386 | 0, | ||||||
387 | "No key passed to test - list_key_scalar - testing - $test_name" | ||||||
388 | ); | ||||||
389 | } | ||||||
390 | 42 | 55 | when ('list_key_ref') { | ||||
391 | return exists $instruction{key} | ||||||
392 | ? is_deeply( | ||||||
393 | {@test}->{ $instruction{key} }, | ||||||
394 | 3 | 100 | 22 | $expected[0], | |||
395 | "$test_name is list - has ref key: $instruction{key} - is_deeply - ref" | ||||||
396 | ) | ||||||
397 | : ok( 0, | ||||||
398 | "No key passed to test - list_key_ref - testing - $test_name" ); | ||||||
399 | } | ||||||
400 | 39 | 50 | when ('list_key_like') { | ||||
401 | return exists $instruction{key} | ||||||
402 | ? like( | ||||||
403 | {@test}->{ $instruction{key} }, | ||||||
404 | 3 | 100 | 48 | qr/$expected[0]/, | |||
405 | "$test_name is list - has scalar key: $instruction{key} - like - $expected[0]" | ||||||
406 | ) | ||||||
407 | : ok( | ||||||
408 | 0, | ||||||
409 | "No key passed to test - list_key_like - testing - $test_name" | ||||||
410 | ); | ||||||
411 | } | ||||||
412 | 36 | 53 | when ('count') { | ||||
413 | 1 | 6 | return is( | ||||
414 | scalar @test, | ||||||
415 | $expected[0], | ||||||
416 | "$test_name is list - count - is - $expected[0]" | ||||||
417 | ); | ||||||
418 | } | ||||||
419 | 35 | 47 | when ('count_ref') { | ||||
420 | return is( | ||||||
421 | 2 | 4 | scalar @{ $test[0] }, | ||||
2 | 10 | ||||||
422 | $expected[0], | ||||||
423 | "$test_name is ref - count - is - $expected[0]" | ||||||
424 | ); | ||||||
425 | } | ||||||
426 | 33 | 48 | when ('scalar') { | ||||
427 | 2 | 50 | 13 | return is( $test[0], $expected[0], sprintf "%s is scalar - is - %s", | |||
428 | $test_name, defined $expected[0] ? $expected[0] : 'undef' ); | ||||||
429 | } | ||||||
430 | 31 | 58 | when ('hash') { | ||||
431 | 3 | 16 | return is_deeply( {@test}, $expected[0], | ||||
432 | "$test_name is hash - reference - is_deeply" ); | ||||||
433 | } | ||||||
434 | 28 | 40 | when ('array') { | ||||
435 | 5 | 25 | return is_deeply( \@test, $expected[0], | ||||
436 | "$test_name is array - reference - is_deeply" ); | ||||||
437 | } | ||||||
438 | 23 | 36 | when ('obj') { | ||||
439 | 7 | 41 | return isa_ok( $test[0], $expected[0], | ||||
440 | "$test_name is Object - blessed - is - $expected[0]" ); | ||||||
441 | } | ||||||
442 | 16 | 21 | when ('like') { | ||||
443 | 3 | 48 | return like( $test[0], qr/$expected[0]/, | ||||
444 | "$test_name is like - $expected[0]" ); | ||||||
445 | } | ||||||
446 | 13 | 16 | when ('true') { | ||||
447 | 2 | 11 | return is( $test[0], 1, "$test_name is true - 1" ); | ||||
448 | } | ||||||
449 | 11 | 15 | when ('false') { | ||||
450 | 2 | 9 | return is( $test[0], 0, "$test_name is false - 0" ); | ||||
451 | } | ||||||
452 | 9 | 12 | when ('undef') { | ||||
453 | 2 | 10 | return is( $test[0], undef, "$test_name is undef" ); | ||||
454 | } | ||||||
455 | 7 | 11 | when ('render') { | ||||
456 | 4 | 12 | return render_me( | ||||
457 | instance => $test[0], | ||||||
458 | expected => $expected[0], | ||||||
459 | ); | ||||||
460 | } | ||||||
461 | 3 | 8 | when ('ok') { | ||||
462 | 2 | 8 | return ok(@test, "$test_name is ok"); | ||||
463 | } | ||||||
464 | 1 | 3 | when ('skip') { | ||||
465 | 1 | 5 | return ok(1, "$test_name - skip"); | ||||
466 | } | ||||||
467 | 0 | 0 | default { | ||||
468 | 0 | 0 | ok(0); | ||||
469 | 0 | 0 | diag "Unknown instruction{test}: $_ passed to moon_test_one"; | ||||
470 | 0 | 0 | return; | ||||
471 | } | ||||||
472 | } | ||||||
473 | } | ||||||
474 | |||||||
475 | =head2 moon_test | ||||||
476 | |||||||
477 | moon_test( | ||||||
478 | name => 'Checking Many Things' | ||||||
479 | build => { | ||||||
480 | class => 'Moonshine::Element', | ||||||
481 | args => { | ||||||
482 | tag => 'p', | ||||||
483 | text => 'hello' | ||||||
484 | } | ||||||
485 | }, | ||||||
486 | instructions => [ | ||||||
487 | { | ||||||
488 | test => 'scalar', | ||||||
489 | func => 'tag', | ||||||
490 | expected => 'p', | ||||||
491 | }, | ||||||
492 | { | ||||||
493 | test => 'scalar', | ||||||
494 | action => 'text', | ||||||
495 | expected => 'hello', | ||||||
496 | }, | ||||||
497 | { | ||||||
498 | test => 'render' | ||||||
499 | expected => ' hello ' |
||||||
500 | }, | ||||||
501 | ], | ||||||
502 | ); | ||||||
503 | |||||||
504 | =head3 name | ||||||
505 | |||||||
506 | The tests name | ||||||
507 | |||||||
508 | name => 'I rule the world', | ||||||
509 | |||||||
510 | =head3 instance | ||||||
511 | |||||||
512 | my $instance = My::Object->new(); | ||||||
513 | instance => $instance, | ||||||
514 | |||||||
515 | =head3 build | ||||||
516 | |||||||
517 | Build an instance | ||||||
518 | |||||||
519 | build => { | ||||||
520 | class => 'My::Object', | ||||||
521 | args => { }, | ||||||
522 | }, | ||||||
523 | |||||||
524 | =head3 instructions | ||||||
525 | |||||||
526 | instructions => [ | ||||||
527 | { | ||||||
528 | test => 'scalar', | ||||||
529 | func => 'tag', | ||||||
530 | expected => 'hello', | ||||||
531 | }, | ||||||
532 | { | ||||||
533 | test => 'scalar', | ||||||
534 | action => 'text', | ||||||
535 | expected => 'hello', | ||||||
536 | }, | ||||||
537 | { | ||||||
538 | test => 'render' | ||||||
539 | expected => ' hello ' |
||||||
540 | }, | ||||||
541 | ], | ||||||
542 | |||||||
543 | =head3 subtest | ||||||
544 | |||||||
545 | instructions => [ | ||||||
546 | { | ||||||
547 | test => 'obj', | ||||||
548 | func => 'glyphicon', | ||||||
549 | args => { switch => 'search' }, | ||||||
550 | subtest => [ | ||||||
551 | { | ||||||
552 | test => 'scalar', | ||||||
553 | func => 'class', | ||||||
554 | expected => 'glyphicon glyphicon-search', | ||||||
555 | }, | ||||||
556 | ... | ||||||
557 | ] | ||||||
558 | } | ||||||
559 | ] | ||||||
560 | |||||||
561 | =cut | ||||||
562 | |||||||
563 | sub moon_test { | ||||||
564 | 7 | 7 | 1 | 1835 | my %instruction = validate_with( | ||
565 | params => \@_, | ||||||
566 | spec => { | ||||||
567 | build => { type => HASHREF, optional => 1, }, | ||||||
568 | instance => { optional => 1, }, | ||||||
569 | instructions => { type => ARRAYREF }, | ||||||
570 | name => { type => SCALAR }, | ||||||
571 | } | ||||||
572 | ); | ||||||
573 | |||||||
574 | my $instance = | ||||||
575 | $instruction{build} | ||||||
576 | ? _build_me( $instruction{build} ) | ||||||
577 | 7 | 50 | 94 | : $instruction{instance}; | |||
578 | |||||||
579 | 7 | 19 | my %test_info = ( | ||||
580 | fail => 0, | ||||||
581 | tested => 0, | ||||||
582 | ); | ||||||
583 | |||||||
584 | 7 | 13 | foreach my $test ( @{ $instruction{instructions} } ) { | ||||
7 | 15 | ||||||
585 | 40 | 13906 | $test_info{tested}++; | ||||
586 | 40 | 100 | 86 | if ( my $subtests = delete $test->{subtest} ) { | |||
587 | my ( $test_name, $new_instance ) = _run_the_code( | ||||||
588 | { | ||||||
589 | instance => $instance, | ||||||
590 | 2 | 3 | %{$test} | ||||
2 | 10 | ||||||
591 | } | ||||||
592 | ); | ||||||
593 | |||||||
594 | $test_info{fail}++ | ||||||
595 | unless moon_test_one( | ||||||
596 | instance => $new_instance, | ||||||
597 | test => $test->{test}, | ||||||
598 | expected => $test->{expected}, | ||||||
599 | 2 | 50 | 135 | ); | |||
600 | |||||||
601 | |||||||
602 | 2 | 832 | my $new_instructions = { | ||||
603 | instance => $new_instance, | ||||||
604 | instructions => $subtests, | ||||||
605 | name => "Subtest -> $instruction{name} -> $test_name", | ||||||
606 | }; | ||||||
607 | |||||||
608 | 2 | 4 | moon_test(%{$new_instructions}); | ||||
2 | 12 | ||||||
609 | 2 | 523 | next; | ||||
610 | } | ||||||
611 | |||||||
612 | $test_info{fail}++ | ||||||
613 | unless moon_test_one( | ||||||
614 | instance => $instance, | ||||||
615 | 38 | 50 | 45 | %{$test} | |||
38 | 135 | ||||||
616 | ); | ||||||
617 | } | ||||||
618 | |||||||
619 | 7 | 50 | 1604 | $test_info{ok} = $test_info{fail} ? 0 : 1; | |||
620 | return ok( | ||||||
621 | $test_info{ok}, | ||||||
622 | sprintf( | ||||||
623 | "moon_test: %s - tested %d instructions - success: %d - failure: %d", | ||||||
624 | $instruction{name}, $test_info{tested}, | ||||||
625 | ( $test_info{tested} - $test_info{fail} ), $test_info{fail}, | ||||||
626 | ) | ||||||
627 | 7 | 55 | ); | ||||
628 | } | ||||||
629 | |||||||
630 | sub _build_me { | ||||||
631 | 3 | 3 | 38 | my %instruction = validate_with( | |||
632 | params => \@_, | ||||||
633 | spec => { | ||||||
634 | class => 1, | ||||||
635 | new => { default => 'new' }, | ||||||
636 | args => { optional => 1, type => HASHREF }, | ||||||
637 | } | ||||||
638 | ); | ||||||
639 | |||||||
640 | 3 | 12 | my $new = $instruction{new}; | ||||
641 | return $instruction{args} | ||||||
642 | ? $instruction{class}->$new( $instruction{args} ) | ||||||
643 | 3 | 50 | 16 | : $instruction{class}->$new; | |||
644 | } | ||||||
645 | |||||||
646 | =head2 render_me | ||||||
647 | |||||||
648 | Test render directly on a Moonshine::Element. | ||||||
649 | |||||||
650 | render_me( | ||||||
651 | instance => $element, | ||||||
652 | expected => ' echo ' |
||||||
653 | ); | ||||||
654 | |||||||
655 | Or test a function.. | ||||||
656 | |||||||
657 | render_me( | ||||||
658 | instance => $instance, | ||||||
659 | func => 'div', | ||||||
660 | args => { data => 'echo' }, | ||||||
661 | expected => ' echo ', |
||||||
662 | ); | ||||||
663 | |||||||
664 | =cut | ||||||
665 | |||||||
666 | sub render_me { | ||||||
667 | 7 | 7 | 1 | 5511 | my %instruction = validate_with( | ||
668 | params => \@_, | ||||||
669 | spec => { | ||||||
670 | instance => 0, | ||||||
671 | func => 0, | ||||||
672 | meth => 0, | ||||||
673 | args => { default => {} }, | ||||||
674 | expected => { type => SCALAR }, | ||||||
675 | } | ||||||
676 | ); | ||||||
677 | |||||||
678 | 7 | 76 | my ( $test_name, $instance ) = _run_the_code( \%instruction ); | ||||
679 | |||||||
680 | return is( $instance->render, | ||||||
681 | 7 | 220 | $instruction{expected}, "render $test_name: $instruction{expected}" ); | ||||
682 | } | ||||||
683 | |||||||
684 | sub _run_the_code { | ||||||
685 | 98 | 98 | 124 | my $instruction = shift; | |||
686 | |||||||
687 | 98 | 121 | my $test_name; | ||||
688 | 98 | 100 | 200 | if ( my $func = $instruction->{func} ) { | |||
100 | |||||||
100 | |||||||
689 | 79 | 144 | $test_name = "function: ${func}"; | ||||
690 | |||||||
691 | return defined $instruction->{args} | ||||||
692 | ? defined $instruction->{args_list} | ||||||
693 | ? ( | ||||||
694 | $test_name, | ||||||
695 | 0 | 0 | $instruction->{instance}->$func( @{ $instruction->{args} } ) | ||||
696 | ) | ||||||
697 | : ( | ||||||
698 | $test_name, $instruction->{instance}->$func( $instruction->{args} // {}) | ||||||
699 | ) | ||||||
700 | 79 | 50 | 50 | 688 | : ( $test_name, $instruction->{instance}->$func ); | ||
100 | |||||||
701 | } | ||||||
702 | elsif ( my $meth = $instruction->{meth} ) { | ||||||
703 | 6 | 35 | my $meth_name = svref_2object($meth)->GV->NAME; | ||||
704 | 6 | 14 | $test_name = "method: ${meth_name}"; | ||||
705 | return | ||||||
706 | defined $instruction->{args_list} | ||||||
707 | 0 | 0 | ? ( $test_name, $meth->( @{ $instruction->{args} } ) ) | ||||
708 | 6 | 50 | 21 | : ( $test_name, $meth->( $instruction->{args} ) ); | |||
709 | } | ||||||
710 | elsif ( exists $instruction->{instance} ) { | ||||||
711 | 12 | 20 | $test_name = 'instance'; | ||||
712 | 12 | 33 | return ( $test_name, $instruction->{instance} ); | ||||
713 | } | ||||||
714 | |||||||
715 | die( | ||||||
716 | 1 | 7 | 'instruction passed to _run_the_code must have a func, meth or instance' | ||||
717 | ); | ||||||
718 | } | ||||||
719 | |||||||
720 | =head2 sunrise | ||||||
721 | |||||||
722 | sunrise(); # done_testing(); | ||||||
723 | |||||||
724 | =cut | ||||||
725 | |||||||
726 | sub sunrise { | ||||||
727 | 6 | 6 | 1 | 36704 | my $done_testing = done_testing(shift); | ||
728 | 6 | 3614 | diag explain $done_testing; | ||||
729 | 6 | 50 | 38803 | diag sprintf( ' | |||
730 | %s | ||||||
731 | ^^ @@@@@@@@@ | ||||||
732 | ^^ ^^ @@@@@@@@@@@@@@@ | ||||||
733 | @@@@@@@@@@@@@@@@@@ ^^ | ||||||
734 | @@@@@@@@@@@@@@@@@@@@ | ||||||
735 | ---- -- ----- -------- -- &&&&&&&&&&&&&&&&&&&& ------- ----------- --- | ||||||
736 | - -- - - -------------------- - -- -- - | ||||||
737 | - -- -- -- -- ------------- ---- - --- - --- - -- | ||||||
738 | - -- - - ------ -- --- -- - -- -- - | ||||||
739 | - - - - - -- ------ - -- - -- | ||||||
740 | - - - - -- - -', | ||||||
741 | shift // ' \o/ ' ); | ||||||
742 | 6 | 1758 | return $done_testing; | ||||
743 | } | ||||||
744 | |||||||
745 | =head1 AUTHOR | ||||||
746 | |||||||
747 | LNATION, C<< |
||||||
748 | |||||||
749 | =head1 BUGS | ||||||
750 | |||||||
751 | Please report any bugs or feature requests to C |
||||||
752 | the web interface at L |
||||||
753 | automatically be notified of progress on your bug as I make changes. | ||||||
754 | |||||||
755 | =head1 SUPPORT | ||||||
756 | |||||||
757 | You can find documentation for this module with the perldoc command. | ||||||
758 | |||||||
759 | perldoc Moonshine::Test | ||||||
760 | |||||||
761 | You can also look for information at: | ||||||
762 | |||||||
763 | =over 4 | ||||||
764 | |||||||
765 | =item * RT: CPAN's request tracker (report bugs here) | ||||||
766 | |||||||
767 | L |
||||||
768 | |||||||
769 | =item * AnnoCPAN: Annotated CPAN documentation | ||||||
770 | |||||||
771 | L |
||||||
772 | |||||||
773 | =item * CPAN Ratings | ||||||
774 | |||||||
775 | L |
||||||
776 | |||||||
777 | =item * Search CPAN | ||||||
778 | |||||||
779 | L |
||||||
780 | |||||||
781 | =back | ||||||
782 | |||||||
783 | =head1 ACKNOWLEDGEMENTS | ||||||
784 | |||||||
785 | =head1 LICENSE AND COPYRIGHT | ||||||
786 | |||||||
787 | Copyright 2017 Robert Acock. | ||||||
788 | |||||||
789 | This program is free software; you can redistribute it and/or modify it | ||||||
790 | under the terms of the the Artistic License (2.0). You may obtain a | ||||||
791 | copy of the full license at: | ||||||
792 | |||||||
793 | L |
||||||
794 | |||||||
795 | Any use, modification, and distribution of the Standard or Modified | ||||||
796 | Versions is governed by this Artistic License. By using, modifying or | ||||||
797 | distributing the Package, you accept this license. Do not use, modify, | ||||||
798 | or distribute the Package, if you do not accept this license. | ||||||
799 | |||||||
800 | If your Modified Version has been derived from a Modified Version made | ||||||
801 | by someone other than you, you are nevertheless required to ensure that | ||||||
802 | your Modified Version complies with the requirements of this license. | ||||||
803 | |||||||
804 | This license does not grant you the right to use any trademark, service | ||||||
805 | mark, tradename, or logo of the Copyright Holder. | ||||||
806 | |||||||
807 | This license includes the non-exclusive, worldwide, free-of-charge | ||||||
808 | patent license to make, have made, use, offer to sell, sell, import and | ||||||
809 | otherwise transfer the Package with respect to any patent claims | ||||||
810 | licensable by the Copyright Holder that are necessarily infringed by the | ||||||
811 | Package. If you institute patent litigation (including a cross-claim or | ||||||
812 | counterclaim) against any party alleging that the Package constitutes | ||||||
813 | direct or contributory patent infringement, then this Artistic License | ||||||
814 | to you shall terminate on the date that such litigation is filed. | ||||||
815 | |||||||
816 | Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER | ||||||
817 | AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. | ||||||
818 | THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||||||
819 | PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY | ||||||
820 | YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR | ||||||
821 | CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR | ||||||
822 | CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, | ||||||
823 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
824 | |||||||
825 | =cut | ||||||
826 | |||||||
827 | 1; # End of Moonshine::Test |