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