📄 more.pm
字号:
my $card = "Eight of clubs"; is( URI::Geller->your_card, $card, 'Is THIS your card?' ); my $spoon; URI::Geller->bend_spoon; is( $spoon, 'bent', "Spoon bending, that's original" ); }With a todo block, the tests inside are expected to fail. Test::Morewill run the tests normally, but print out special flags indicatingthey are "todo". Test::Harness will interpret failures as being ok.Should anything succeed, it will report it as an unexpected success.You then know the thing you had todo is done and can remove theTODO flag.The nice part about todo tests, as opposed to simply commenting out ablock of tests, is it's like having a programmatic todo list. You knowhow much work is left to be done, you're aware of what bugs there are,and you'll know immediately when they're fixed.Once a todo test starts succeeding, simply move it outside the block.When the block is empty, delete it.B<NOTE>: TODO tests require a Test::Harness upgrade else it willtreat it as a normal failure. See L<CAVEATS and NOTES>).=item B<todo_skip> TODO: { todo_skip $why, $how_many if $condition; ...normal testing code... }With todo tests, it's best to have the tests actually run. That wayyou'll know when they start passing. Sometimes this isn't possible.Often a failing test will cause the whole program to die or hang, eveninside an C<eval BLOCK> with and using C<alarm>. In these extremecases you have no choice but to skip over the broken tests entirely.The syntax and behavior is similar to a C<SKIP: BLOCK> except thetests will be marked as failing but todo. Test::Harness willinterpret them as passing.=cutsub todo_skip { my($why, $how_many) = @_; my $tb = Test::More->builder; unless( defined $how_many ) { # $how_many can only be avoided when no_plan is in use. _carp "todo_skip() needs to know \$how_many tests are in the block" unless $tb->has_plan eq 'no_plan'; $how_many = 1; } for( 1..$how_many ) { $tb->todo_skip($why); } local $^W = 0; last TODO;}=item When do I use SKIP vs. TODO?B<If it's something the user might not be able to do>, use SKIP.This includes optional modules that aren't installed, running underan OS that doesn't have some feature (like fork() or symlinks), or maybeyou need an Internet connection and one isn't available.B<If it's something the programmer hasn't done yet>, use TODO. Thisis for any code you haven't written yet, or bugs you have yet to fix,but want to put tests in your testing script (always a good idea).=back=head2 Test control=over 4=item B<BAIL_OUT> BAIL_OUT($reason);Indicates to the harness that things are going so badly all testingshould terminate. This includes the running any additional test scripts.This is typically used when testing cannot continue such as a criticalmodule failing to compile or a necessary external utility not beingavailable such as a database connection failing.The test will exit with 255.=cutsub BAIL_OUT { my $reason = shift; my $tb = Test::More->builder; $tb->BAIL_OUT($reason);}=back=head2 Discouraged comparison functionsThe use of the following functions is discouraged as they are notactually testing functions and produce no diagnostics to help figureout what went wrong. They were written before is_deeply() existedbecause I couldn't figure out how to display a useful diff of twoarbitrary data structures.These functions are usually used inside an ok(). ok( eq_array(\@got, \@expected) );C<is_deeply()> can do that better and with diagnostics. is_deeply( \@got, \@expected );They may be deprecated in future versions.=over 4=item B<eq_array> my $is_eq = eq_array(\@got, \@expected);Checks if two arrays are equivalent. This is a deep check, somulti-level structures are handled correctly.=cut#'#sub eq_array { local @Data_Stack; _deep_check(@_);}sub _eq_array { my($a1, $a2) = @_; if( grep !_type($_) eq 'ARRAY', $a1, $a2 ) { warn "eq_array passed a non-array ref"; return 0; } return 1 if $a1 eq $a2; my $ok = 1; my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2; for (0..$max) { my $e1 = $_ > $#$a1 ? $DNE : $a1->[$_]; my $e2 = $_ > $#$a2 ? $DNE : $a2->[$_]; push @Data_Stack, { type => 'ARRAY', idx => $_, vals => [$e1, $e2] }; $ok = _deep_check($e1,$e2); pop @Data_Stack if $ok; last unless $ok; } return $ok;}sub _deep_check { my($e1, $e2) = @_; my $tb = Test::More->builder; my $ok = 0; # Effectively turn %Refs_Seen into a stack. This avoids picking up # the same referenced used twice (such as [\$a, \$a]) to be considered # circular. local %Refs_Seen = %Refs_Seen; { # Quiet uninitialized value warnings when comparing undefs. local $^W = 0; $tb->_unoverload_str(\$e1, \$e2); # Either they're both references or both not. my $same_ref = !(!ref $e1 xor !ref $e2); my $not_ref = (!ref $e1 and !ref $e2); if( defined $e1 xor defined $e2 ) { $ok = 0; } elsif ( _dne($e1) xor _dne($e2) ) { $ok = 0; } elsif ( $same_ref and ($e1 eq $e2) ) { $ok = 1; } elsif ( $not_ref ) { push @Data_Stack, { type => '', vals => [$e1, $e2] }; $ok = 0; } else { if( $Refs_Seen{$e1} ) { return $Refs_Seen{$e1} eq $e2; } else { $Refs_Seen{$e1} = "$e2"; } my $type = _type($e1); $type = 'DIFFERENT' unless _type($e2) eq $type; if( $type eq 'DIFFERENT' ) { push @Data_Stack, { type => $type, vals => [$e1, $e2] }; $ok = 0; } elsif( $type eq 'ARRAY' ) { $ok = _eq_array($e1, $e2); } elsif( $type eq 'HASH' ) { $ok = _eq_hash($e1, $e2); } elsif( $type eq 'REF' ) { push @Data_Stack, { type => $type, vals => [$e1, $e2] }; $ok = _deep_check($$e1, $$e2); pop @Data_Stack if $ok; } elsif( $type eq 'SCALAR' ) { push @Data_Stack, { type => 'REF', vals => [$e1, $e2] }; $ok = _deep_check($$e1, $$e2); pop @Data_Stack if $ok; } elsif( $type ) { push @Data_Stack, { type => $type, vals => [$e1, $e2] }; $ok = 0; } else { _whoa(1, "No type in _deep_check"); } } } return $ok;}sub _whoa { my($check, $desc) = @_; if( $check ) { die <<WHOA;WHOA! $descThis should never happen! Please contact the author immediately!WHOA }}=item B<eq_hash> my $is_eq = eq_hash(\%got, \%expected);Determines if the two hashes contain the same keys and values. Thisis a deep check.=cutsub eq_hash { local @Data_Stack; return _deep_check(@_);}sub _eq_hash { my($a1, $a2) = @_; if( grep !_type($_) eq 'HASH', $a1, $a2 ) { warn "eq_hash passed a non-hash ref"; return 0; } return 1 if $a1 eq $a2; my $ok = 1; my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2; foreach my $k (keys %$bigger) { my $e1 = exists $a1->{$k} ? $a1->{$k} : $DNE; my $e2 = exists $a2->{$k} ? $a2->{$k} : $DNE; push @Data_Stack, { type => 'HASH', idx => $k, vals => [$e1, $e2] }; $ok = _deep_check($e1, $e2); pop @Data_Stack if $ok; last unless $ok; } return $ok;}=item B<eq_set> my $is_eq = eq_set(\@got, \@expected);Similar to eq_array(), except the order of the elements is B<not>important. This is a deep check, but the irrelevancy of order onlyapplies to the top level. ok( eq_set(\@got, \@expected) );Is better written: is_deeply( [sort @got], [sort @expected] );B<NOTE> By historical accident, this is not a true set comparison.While the order of elements does not matter, duplicate elements do.B<NOTE> eq_set() does not know how to deal with references at the toplevel. The following is an example of a comparison which might not work: eq_set([\1, \2], [\2, \1]);Test::Deep contains much better set comparison functions.=cutsub eq_set { my($a1, $a2) = @_; return 0 unless @$a1 == @$a2; # There's faster ways to do this, but this is easiest. local $^W = 0; # It really doesn't matter how we sort them, as long as both arrays are # sorted with the same algorithm. # # Ensure that references are not accidentally treated the same as a # string containing the reference. # # Have to inline the sort routine due to a threading/sort bug. # See [rt.cpan.org 6782] # # I don't know how references would be sorted so we just don't sort # them. This means eq_set doesn't really work with refs. return eq_array( [grep(ref, @$a1), sort( grep(!ref, @$a1) )], [grep(ref, @$a2), sort( grep(!ref, @$a2) )], );}=back=head2 Extending and Embedding Test::MoreSometimes the Test::More interface isn't quite enough. Fortunately,Test::More is built on top of Test::Builder which provides a single,unified backend for any test library to use. This means two testlibraries which both use Test::Builder B<can be used together in thesame program>.If you simply want to do a little tweaking of how the tests behave,you can access the underlying Test::Builder object like so:=over 4=item B<builder> my $test_builder = Test::More->builder;Returns the Test::Builder object underlying Test::More for you to playwith.=back=head1 EXIT CODESIf all your tests passed, Test::Builder will exit with zero (which isnormal). If anything failed it will exit with how many failed. Ifyou run less (or more) tests than you planned, the missing (or extras)will be considered failures. If no tests were ever run Test::Builderwill throw a warning and exit with 255. If the test died, even afterhaving successfully completed all its tests, it will still beconsidered a failure and will exit with 255.So the exit codes are... 0 all tests successful 255 test died or all passed but wrong # of tests run any other number how many failed (including missing or extras)If you fail more than 254 tests, it will be reported as 254.B<NOTE> This behavior may go away in future versions.=head1 CAVEATS and NOTES=over 4=item Backwards compatibilityTest::More works with Perls as old as 5.004_05.=item Overloaded objectsString overloaded objects are compared B<as strings> (or in cmp_ok()'scase, strings or numbers as appropriate to the comparison op). Thisprevents Test::More from piercing an object's interface allowingbetter blackbox testing. So if a function starts returning overloadedobjects instead of bare strings your tests won't notice thedifference. This is good.However, it does mean that functions like is_deeply() cannot be used totest the internals of string overloaded objects. In this case I wouldsuggest Test::Deep which contains more flexible testing functions forcomplex data structures.=item ThreadsTest::More will only be aware of threads if "use threads" has been doneI<before> Test::More is loaded. This is ok: use threads; use Test::More;This may cause problems: use Test::More use threads;5.8.1 and above are supported. Anything below that has too many bugs.=item Test::Harness upgradeno_plan and todo depend on new Test::Harness features and fixes. Ifyou're going to distribute tests that use no_plan or todo yourend-users will have to upgrade Test::Harness to the latest one onCPAN. If you avoid no_plan and TODO tests, the stock Test::Harnesswill work fine.Installing Test::More should also upgrade Test::Harness.=back=head1 HISTORYThis is a case of convergent evolution with Joshua Pritikin's Testmodule. I was largely unaware of its existence when I'd firstwritten my own ok() routines. This module exists because I can'tfigure out how to easily wedge test names into Test's interface (alongwith a few other problems).The goal here is to have a testing utility that's simple to learn,quick to use and difficult to trip yourself up with while stillproviding more flexibility than the existing Test.pm. As such, thenames of the most common routines are kept tiny, special cases andmagic side-effects are kept to a minimum. WYSIWYG.=head1 SEE ALSOL<Test::Simple> if all this confuses you and you just want to writesome tests. You can upgrade to Test::More later (it's forwardcompatible).L<Test> is the old testing module. Its main benefit is that it hasbeen distributed with Perl since 5.004_05.L<Test::Harness> for details on how your test results are interpretedby Perl.L<Test::Differences> for more ways to test complex data structures.And it plays well with Test::More.L<Test::Class> is like XUnit but more perlish.L<Test::Deep> gives you more powerful complex data structure testing.L<Test::Unit> is XUnit style testing.L<Test::Inline> shows the idea of embedded testing.L<Bundle::Test> installs a whole bunch of useful test modules.=head1 AUTHORSMichael G Schwern E<lt>schwern@pobox.comE<gt> with much inspirationfrom Joshua Pritikin's Test module and lots of help from BarrieSlaymaker, Tony Bowden, blackstar.co.uk, chromatic, Fergal Daly andthe perl-qa gang.=head1 BUGSSee F<http://rt.cpan.org> to report and view bugs.=head1 COPYRIGHTCopyright 2001-2002, 2004-2006 by Michael G Schwern E<lt>schwern@pobox.comE<gt>.This program is free software; you can redistribute it and/ormodify it under the same terms as Perl itself.See F<http://www.perl.com/perl/misc/Artistic.html>=cut1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -