📄 more.pm
字号:
=cutsub isa_ok ($$) { my($object, $class) = @_; my $diag; my $name = "object->isa('$class')"; if( !defined $object ) { $diag = "The object isn't defined"; } elsif( !ref $object ) { $diag = "The object isn't a reference"; } elsif( !$object->isa($class) ) { $diag = "The object isn't a '$class'"; } if( $diag ) { ok( 0, $name ); my_print *TESTERR, "# $diag\n"; return 0; } else { ok( 1, $name ); return 1; }}=item B<pass>=item B<fail> pass($test_name); fail($test_name);Sometimes you just want to say that the tests have passed. Usuallythe case is you've got some complicated condition that is difficult towedge into an ok(). In this case, you can simply use pass() (todeclare the test ok) or fail (for not ok). They are synonyms forok(1) and ok(0).Use these very, very, very sparingly.=cutsub pass (;$) { my($name) = @_; return @_ == 1 ? ok(1, $name) : ok(1);}sub fail (;$) { my($name) = @_; return @_ == 1 ? ok(0, $name) : ok(0);}=back=head2 Module testsYou usually want to test if the module you're testing loads ok, ratherthan just vomiting if its load fails. For such purposes we haveC<use_ok> and C<require_ok>.=over 4=item B<use_ok> BEGIN { use_ok($module); } BEGIN { use_ok($module, @imports); }These simply use the given $module and test to make sure the loadhappened ok. Its recommended that you run use_ok() inside a BEGINblock so its functions are exported at compile-time and prototypes areproperly honored.If @imports are given, they are passed through to the use. So this: BEGIN { use_ok('Some::Module', qw(foo bar)) }is like doing this: use Some::Module qw(foo bar);=cutsub use_ok ($;@) { my($module, @imports) = @_; @imports = () unless @imports; my $pack = caller; eval <<USE;package $pack;require $module;$module->import(\@imports);USE my $ok = ok( !$@, "use $module;" ); unless( $ok ) { my_print *TESTERR, <<DIAGNOSTIC;# Tried to use '$module'.# Error: $@DIAGNOSTIC } return $ok;}=item B<require_ok> require_ok($module);Like use_ok(), except it requires the $module.=cutsub require_ok ($) { my($module) = shift; my $pack = caller; eval <<REQUIRE;package $pack;require $module;REQUIRE my $ok = ok( !$@, "require $module;" ); unless( $ok ) { my_print *TESTERR, <<DIAGNOSTIC;# Tried to require '$module'.# Error: $@DIAGNOSTIC } return $ok;}=back=head2 Conditional testsB<WARNING!> The following describes an I<experimental> interface thatis subject to change B<WITHOUT NOTICE>! Use at your peril.Sometimes running a test under certain conditions will cause thetest script to die. A certain function or method isn't implemented(such as fork() on MacOS), some resource isn't available (like a net connection) or a module isn't available. In these cases it'snecessary to skip tests, or declare that they are supposed to failbut will work in the future (a todo test).For more details on skip and todo tests see L<Test::Harness>.The way Test::More handles this is with a named block. Basically, ablock of tests which can be skipped over or made todo. It's best if Ijust show you...=over 4=item B<SKIP: BLOCK> SKIP: { skip $why, $how_many if $condition; ...normal testing code goes here... }This declares a block of tests to skip, $how_many tests there are,$why and under what $condition to skip them. An example is theeasiest way to illustrate: SKIP: { skip "Pigs don't fly here", 2 unless Pigs->can('fly'); my $pig = Pigs->new; $pig->takeoff; ok( $pig->altitude > 0, 'Pig is airborne' ); ok( $pig->airspeed > 0, ' and moving' ); }If pigs cannot fly, the whole block of tests will be skippedcompletely. Test::More will output special ok's which Test::Harnessinterprets as skipped tests. Its important to include $how_many testsare in the block so the total number of tests comes out right (unlessyou're using C<no_plan>).You'll typically use this when a feature is missing, like an optionalmodule is not installed or the operating system doesn't have somefeature (like fork() or symlinks) or maybe you need an Internetconnection and one isn't available.=for _FutureSee L</Why are skip and todo so weird?>=cut#'#sub skip { my($why, $how_many) = @_; unless( $how_many >= 1 ) { # $how_many can only be avoided when no_plan is in use. carp "skip() needs to know \$how_many tests are in the block" if $Test::Simple::Planned_Tests; $how_many = 1; } for( 1..$how_many ) { Test::Simple::_skipped($why); } local $^W = 0; last SKIP;}=item B<TODO: BLOCK> TODO: { local $TODO = $why; ...normal testing code goes here... }Declares a block of tests you expect to fail and $why. Perhaps it'sbecause you haven't fixed a bug or haven't finished a new feature: TODO: { local $TODO = "URI::Geller not finished"; 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.The nice part about todo tests, as opposed to simply commenting out ablock of tests, is it's like having a programatic 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.=back=head2 Comparision functionsNot everything is a simple eq check or regex. There are times youneed to see if two arrays are equivalent, for instance. For theseinstances, Test::More provides a handful of useful functions.B<NOTE> These are NOT well-tested on circular references. Nor am Iquite sure what will happen with filehandles.=over 4=item B<eq_array> eq_array(\@this, \@that);Checks if two arrays are equivalent. This is a deep check, somulti-level structures are handled correctly.=cut#'#sub eq_array { my($a1, $a2) = @_; return 0 unless @$a1 == @$a2; return 1 if $a1 eq $a2; my $ok = 1; for (0..$#{$a1}) { my($e1,$e2) = ($a1->[$_], $a2->[$_]); $ok = _deep_check($e1,$e2); last unless $ok; } return $ok;}sub _deep_check { my($e1, $e2) = @_; my $ok = 0; my $eq; { # Quiet unintialized value warnings when comparing undefs. local $^W = 0; if( $e1 eq $e2 ) { $ok = 1; } else { if( UNIVERSAL::isa($e1, 'ARRAY') and UNIVERSAL::isa($e2, 'ARRAY') ) { $ok = eq_array($e1, $e2); } elsif( UNIVERSAL::isa($e1, 'HASH') and UNIVERSAL::isa($e2, 'HASH') ) { $ok = eq_hash($e1, $e2); } else { $ok = 0; } } } return $ok;}=item B<eq_hash> eq_hash(\%this, \%that);Determines if the two hashes contain the same keys and values. Thisis a deep check.=cutsub eq_hash { my($a1, $a2) = @_; return 0 unless keys %$a1 == keys %$a2; return 1 if $a1 eq $a2; my $ok = 1; foreach my $k (keys %$a1) { my($e1, $e2) = ($a1->{$k}, $a2->{$k}); $ok = _deep_check($e1, $e2); last unless $ok; } return $ok;}=item B<eq_set> eq_set(\@this, \@that);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.=cut# We must make sure that references are treated neutrally. It really# doesn't matter how we sort them, as long as both arrays are sorted# with the same algorithm.sub _bogus_sort { local $^W = 0; ref $a ? 0 : $a cmp $b }sub eq_set { my($a1, $a2) = @_; return 0 unless @$a1 == @$a2; # There's faster ways to do this, but this is easiest. return eq_array( [sort _bogus_sort @$a1], [sort _bogus_sort @$a2] );}=back=head1 NOTESTest::More is B<explicitly> tested all the way back to perl 5.004.=head1 BUGS and CAVEATS=over 4=item Making your own ok()This will not do what you mean: sub my_ok { ok( @_ ); } my_ok( 2 + 2 == 5, 'Basic addition' );since ok() takes it's arguments as scalars, it will see the length of@_ (2) and always pass the test. You want to do this instead: sub my_ok { ok( $_[0], $_[1] ); }The other functions act similiarly.=item The eq_* family have some caveats.=item Test::Harness upgradesno_plan and todo depend on new Test::Harness features and fixes. Ifyou're going to distribute tests that use no_plan your end-users willhave to upgrade Test::Harness to the latest one on CPAN.If you simply depend on Test::More, it's own dependencies will cause aTest::Harness upgrade.=back=head1 AUTHORMichael G Schwern E<lt>schwern@pobox.comE<gt> with much inspiration fromJoshua Pritikin's Test module and lots of discussion with BarrieSlaymaker and the perl-qa gang.=head1 HISTORYThis is a case of convergent evolution with Joshua Pritikin's Testmodule. I was largely unware 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 (its forwardcompatible).L<Test> for a similar testing module.L<Test::Harness> for details on how your test results are interpretedby Perl.L<Test::Unit> describes a very featureful unit testing interface.L<Pod::Tests> shows the idea of embedded testing.L<SelfTest> is another approach to embedded testing.=cut1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -