📄 tester.pm
字号:
package Test::Builder::Tester;use strict;use vars qw(@EXPORT $VERSION @ISA);$VERSION = "1.11";use Test::Builder;use Symbol;use Carp;=head1 NAMETest::Builder::Tester - test testsuites that have been built withTest::Builder=head1 SYNOPSIS use Test::Builder::Tester tests => 1; use Test::More; test_out("not ok 1 - foo"); test_fail(+1); fail("foo"); test_test("fail works");=head1 DESCRIPTIONA module that helps you test testing modules that are built withB<Test::Builder>.The testing system is designed to be used by performing a three stepprocess for each test you wish to test. This process starts with usingC<test_out> and C<test_err> in advance to declare what the testsuite youare testing will output with B<Test::Builder> to stdout and stderr.You then can run the test(s) from your test suite that callB<Test::Builder>. At this point the output of B<Test::Builder> issafely captured by B<Test::Builder::Tester> rather than beinginterpreted as real test output.The final stage is to call C<test_test> that will simply compare what youpredeclared to what B<Test::Builder> actually outputted, and report theresults back with a "ok" or "not ok" (with debugging) to the normaloutput.=cut##### set up testing####my $t = Test::Builder->new;#### make us an exporter###use Exporter;@ISA = qw(Exporter);@EXPORT = qw(test_out test_err test_fail test_diag test_test line_num);# _export_to_level and import stolen directly from Test::More. I am# the king of cargo cult programming ;-)# 5.004's Exporter doesn't have export_to_level.sub _export_to_level{ my $pkg = shift; my $level = shift; (undef) = shift; # XXX redundant arg my $callpkg = caller($level); $pkg->export($callpkg, @_);}sub import { my $class = shift; my(@plan) = @_; my $caller = caller; $t->exported_to($caller); $t->plan(@plan); my @imports = (); foreach my $idx (0..$#plan) { if( $plan[$idx] eq 'import' ) { @imports = @{$plan[$idx+1]}; last; } } __PACKAGE__->_export_to_level(1, __PACKAGE__, @imports);}#### set up file handles#### create some private file handlesmy $output_handle = gensym;my $error_handle = gensym;# and tie them to this packagemy $out = tie *$output_handle, "Test::Builder::Tester::Tie", "STDOUT";my $err = tie *$error_handle, "Test::Builder::Tester::Tie", "STDERR";##### exported functions##### for remembering that we're testing and where we're testing atmy $testing = 0;my $testing_num;# remembering where the file handles were originally connectedmy $original_output_handle;my $original_failure_handle;my $original_todo_handle;my $original_test_number;my $original_harness_state;my $original_harness_env;# function that starts testing and redirects the filehandles for nowsub _start_testing{ # even if we're running under Test::Harness pretend we're not # for now. This needed so Test::Builder doesn't add extra spaces $original_harness_env = $ENV{HARNESS_ACTIVE} || 0; $ENV{HARNESS_ACTIVE} = 0; # remember what the handles were set to $original_output_handle = $t->output(); $original_failure_handle = $t->failure_output(); $original_todo_handle = $t->todo_output(); # switch out to our own handles $t->output($output_handle); $t->failure_output($error_handle); $t->todo_output($error_handle); # clear the expected list $out->reset(); $err->reset(); # remeber that we're testing $testing = 1; $testing_num = $t->current_test; $t->current_test(0); # look, we shouldn't do the ending stuff $t->no_ending(1);}=head2 FunctionsThese are the six methods that are exported as default.=over 4=item test_out=item test_errProcedures for predeclaring the output that your test suite isexpected to produce until C<test_test> is called. These proceduresautomatically assume that each line terminates with "\n". So test_out("ok 1","ok 2");is the same as test_out("ok 1\nok 2");which is even the same as test_out("ok 1"); test_out("ok 2");Once C<test_out> or C<test_err> (or C<test_fail> or C<test_diag>) havebeen called once all further output from B<Test::Builder> will becaptured by B<Test::Builder::Tester>. This means that your will notbe able perform further tests to the normal output in the normal wayuntil you call C<test_test> (well, unless you manually meddle with theoutput filehandles)=cutsub test_out(@){ # do we need to do any setup? _start_testing() unless $testing; $out->expect(@_)}sub test_err(@){ # do we need to do any setup? _start_testing() unless $testing; $err->expect(@_)}=item test_failBecause the standard failure message that B<Test::Builder> produceswhenever a test fails will be a common occurrence in your test erroroutput, and because has changed between Test::Builder versions, ratherthan forcing you to call C<test_err> with the string all the time likeso test_err("# Failed test ($0 at line ".line_num(+1).")");C<test_fail> exists as a convenience function that can be calledinstead. It takes one argument, the offset from the current line thatthe line that causes the fail is on. test_fail(+1);This means that the example in the synopsis could be rewrittenmore simply as: test_out("not ok 1 - foo"); test_fail(+1); fail("foo"); test_test("fail works");=cutsub test_fail{ # do we need to do any setup? _start_testing() unless $testing; # work out what line we should be on my ($package, $filename, $line) = caller; $line = $line + (shift() || 0); # prevent warnings # expect that on stderr $err->expect("# Failed test ($0 at line $line)");}=item test_diagAs most of the remaining expected output to the error stream will becreated by Test::Builder's C<diag> function, B<Test::Builder::Tester>provides a convience function C<test_diag> that you can use instead ofC<test_err>.The C<test_diag> function prepends comment hashes and spacing to thestart and newlines to the end of the expected output passed to it andadds it to the list of expected error output. So, instead of writing test_err("# Couldn't open file");you can write test_diag("Couldn't open file");Remember that B<Test::Builder>'s diag function will not add newlines tothe end of output and test_diag will. So to check Test::Builder->new->diag("foo\n","bar\n");You would do test_diag("foo","bar")without the newlines.=cutsub test_diag{ # do we need to do any setup? _start_testing() unless $testing; # expect the same thing, but prepended with "# " local $_; $err->expect(map {"# $_"} @_)}=item test_testActually performs the output check testing the tests, comparing thedata (with C<eq>) that we have captured from B<Test::Builder> againstthat that was declared with C<test_out> and C<test_err>.This takes name/value pairs that effect how the test is run.=over=item title (synonym 'name', 'label')The name of the test that will be displayed after the C<ok> or C<notok>.=item skip_outSetting this to a true value will cause the test to ignore if theoutput sent by the test to the output stream does not match thatdeclared with C<test_out>.=item skip_errSetting this to a true value will cause the test to ignore if theoutput sent by the test to the error stream does not match thatdeclared with C<test_err>.=backAs a convience, if only one argument is passed then this argumentis assumed to be the name of the test (as in the above examples.)Once C<test_test> has been run test output will be redirected back tothe original filehandles that B<Test::Builder> was connected to(probably STDOUT and STDERR,) meaning any further tests you runwill function normally and cause success/errors for B<Test::Harness>.=cut
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -