home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Tester.pm < prev    next >
Encoding:
Perl POD Document  |  2002-05-01  |  13.1 KB  |  542 lines

  1. package Test::Builder::Tester;
  2.  
  3. use strict;
  4. use vars qw(@EXPORT $VERSION @ISA);
  5. $VERSION = 0.09;
  6.  
  7. use Test::Builder;
  8. use Symbol;
  9. use Carp;
  10.  
  11. =head1 NAME
  12.  
  13. Test::Builder::Tester - test testsuites that have been built with
  14. Test::Builder
  15.  
  16. =head1 SYNOPSIS
  17.  
  18.     use Test::Builder::Tester tests => 1;
  19.     use Test::More;
  20.  
  21.     test_out("not ok 1 - foo");
  22.     test_err("# Failed test ($0 at line ".line_num(+1).")");
  23.     fail("foo");
  24.     test_test("fail works");
  25.  
  26. =head1 DESCRIPTION
  27.  
  28. A module that helps you test testing modules that are built with
  29. B<Test::Builder>.
  30.  
  31. The testing system is designed to be used by performing a three step
  32. process for each test you wish to test.  This process starts with using
  33. C<test_out> and C<test_err> in advance to declare what the testsuite you
  34. are testing will output with B<Test::Builder> to stdout and stderr.
  35.  
  36. You then can run the test(s) from your test suite that call
  37. B<Test::Builder>.  At this point the output of B<Test::Builder> is
  38. safely captured by B<Test::Builder::Tester> rather than being
  39. interpreted as real test output.
  40.  
  41. The final stage is to call C<test_test> that will simply compare what you
  42. predeclared to what B<Test::Builder> actually outputted, and report the
  43. results back with a "ok" or "not ok" (with debugging) to the normal
  44. output.
  45.  
  46. =cut
  47.  
  48. ####
  49. # set up testing
  50. ####
  51.  
  52. my $t = Test::Builder->new;
  53.  
  54. ###
  55. # make us an exporter
  56. ###
  57.  
  58. use Exporter;
  59. @ISA = qw(Exporter);
  60.  
  61. @EXPORT = qw(test_out test_err test_fail test_diag test_test line_num);
  62.  
  63. # _export_to_level and import stolen directly from Test::More.  I am
  64. # the king of cargo cult programming ;-)
  65.  
  66. # 5.004's Exporter doesn't have export_to_level.
  67. sub _export_to_level
  68. {
  69.       my $pkg = shift;
  70.       my $level = shift;
  71.       (undef) = shift;                  # XXX redundant arg
  72.       my $callpkg = caller($level);
  73.       $pkg->export($callpkg, @_);
  74. }
  75.  
  76. sub import {
  77.     my $class = shift;
  78.     my(@plan) = @_;
  79.  
  80.     my $caller = caller;
  81.  
  82.     $t->exported_to($caller);
  83.     $t->plan(@plan);
  84.  
  85.     my @imports = ();
  86.     foreach my $idx (0..$#plan) {
  87.         if( $plan[$idx] eq 'import' ) {
  88.             @imports = @{$plan[$idx+1]};
  89.             last;
  90.         }
  91.     }
  92.  
  93.     __PACKAGE__->_export_to_level(1, __PACKAGE__, @imports);
  94. }
  95.  
  96. ###
  97. # set up file handles
  98. ###
  99.  
  100. # create some private file handles
  101. my $output_handle = gensym;
  102. my $error_handle  = gensym;
  103.  
  104. # and tie them to this package
  105. my $out = tie *$output_handle, "Test::Tester::Tie", "STDOUT";
  106. my $err = tie *$error_handle,  "Test::Tester::Tie", "STDERR";
  107.  
  108. ####
  109. # exported functions
  110. ####
  111.  
  112. # for remembering that we're testing and where we're testing at
  113. my $testing = 0;
  114. my $testing_num;
  115.  
  116. # remembering where the file handles were originally connected
  117. my $original_output_handle;
  118. my $original_failure_handle;
  119. my $original_todo_handle;
  120.  
  121. my $original_test_number;
  122.  
  123. # function that starts testing and redirects the filehandles for now
  124. sub _start_testing
  125. {
  126.     # remember what the handles were set to
  127.     $original_output_handle  = $t->output();
  128.     $original_failure_handle = $t->failure_output();
  129.     $original_todo_handle    = $t->todo_output();
  130.  
  131.     # switch out to our own handles
  132.     $t->output($output_handle);
  133.     $t->failure_output($error_handle);
  134.     $t->todo_output($error_handle);
  135.  
  136.     # clear the expected list
  137.     $out->reset();
  138.     $err->reset();
  139.  
  140.     # remeber that we're testing
  141.     $testing = 1;
  142.     $testing_num = $t->current_test;
  143.     $t->current_test(0);
  144.  
  145.     # look, we shouldn't do the ending stuff
  146.     $t->no_ending(1);
  147. }
  148.  
  149. =head2 Methods
  150.  
  151. These are the six methods that are exported as default.
  152.  
  153. =over 4
  154.  
  155. =item test_out
  156.  
  157. =item test_err
  158.  
  159. Procedures for predeclaring the output that your test suite is
  160. expected to produce until C<test_test> is called.  These procedures
  161. automatically assume that each line terminates with "\n".  So
  162.  
  163.    test_out("ok 1","ok 2");
  164.  
  165. is the same as
  166.  
  167.    test_out("ok 1\nok 2");
  168.  
  169. which is even the same as
  170.  
  171.    test_out("ok 1");
  172.    test_out("ok 2");
  173.  
  174. Once C<test_out> or C<test_err> (or C<test_fail> or C<test_diag>) have
  175. been called once all further output from B<Test::Builder> will be
  176. captured by B<Test::Builder::Tester>.  This means that your will not
  177. be able perform further tests to the normal output in the normal way
  178. until you call C<test_test> (well, unless you manually meddle with the
  179. output filehandles)
  180.  
  181. =cut
  182.  
  183. sub test_out(@)
  184. {
  185.     # do we need to do any setup?
  186.     _start_testing() unless $testing;
  187.  
  188.     $out->expect(@_)
  189. }
  190.  
  191. sub test_err(@)
  192. {
  193.     # do we need to do any setup?
  194.     _start_testing() unless $testing;
  195.  
  196.     $err->expect(@_)
  197. }
  198.  
  199. =item test_fail
  200.  
  201. Because the standard failure message that B<Test::Builder> produces
  202. whenever a test fails will be a common occurrence in your test error
  203. output, rather than forcing you to call C<test_err> with the string
  204. all the time like so
  205.  
  206.     test_err("# Failed test ($0 at line ".line_num(+1).")");
  207.  
  208. C<test_fail> exists as a convenience method that can be called
  209. instead.  It takes one argument, the offset from the current line that
  210. the line that causes the fail is on.
  211.  
  212.     test_fail(+1);
  213.  
  214. This means that the example in the synopsis could be rewritten
  215. more simply as:
  216.  
  217.    test_out("not ok 1 - foo");
  218.    test_fail(+1);
  219.    fail("foo");
  220.    test_test("fail works");
  221.  
  222. =cut
  223.  
  224. sub test_fail
  225. {
  226.     # do we need to do any setup?
  227.     _start_testing() unless $testing;
  228.  
  229.     # work out what line we should be on
  230.     my ($package, $filename, $line) = caller;
  231.     $line = $line + (shift() || 0); # prevent warnings
  232.  
  233.     # expect that on stderr
  234.     $err->expect("#     Failed test ($0 at line $line)");
  235. }
  236.  
  237. =item test_diag
  238.  
  239. As most of the remaining expected output to the error stream will be
  240. created by Test::Builder's C<diag> function, B<Test::Builder::Tester>
  241. provides a convience function C<test_diag> that you can use instead of
  242. C<test_err>.
  243.  
  244. The C<test_diag> function prepends comment hashes and spacing to the
  245. start and newlines to the end of the expected output passed to it and
  246. adds it to the list of expected error output.  So, instead of writing
  247.  
  248.    test_err("# Couldn't open file");
  249.  
  250. you can write
  251.  
  252.    test_diag("Couldn't open file");
  253.  
  254. Remember that B<Test::Builder>'s diag function will not add newlines to
  255. the end of output and test_diag will. So to check
  256.  
  257.    Test::Builder->new->diag("foo\n","bar\n");
  258.  
  259. You would do
  260.  
  261.   test_diag("foo","bar")
  262.  
  263. without the newlines.
  264.  
  265. =cut
  266.  
  267. sub test_diag
  268. {
  269.     # do we need to do any setup?
  270.     _start_testing() unless $testing;
  271.  
  272.     # expect the same thing, but prepended with "#     "
  273.     local $_;
  274.     $err->expect(map {"# $_"} @_)
  275. }
  276.  
  277. =item test_test
  278.  
  279. Actually performs the output check testing the tests, comparing the
  280. data (with C<eq>) that we have captured from B<Test::Builder> against
  281. that that was declared with C<test_out> and C<test_err>.
  282.  
  283. Optionally takes a name for the test as its only argument.
  284.  
  285. Once C<test_test> has been run test output will be redirected back to
  286. the original filehandles that B<Test::Builder> was connected to
  287. (probably STDOUT and STDERR)
  288.  
  289. =cut
  290.  
  291. sub test_test(;$)
  292. {
  293.     my $mess = shift;
  294.  
  295.     # er, are we testing?
  296.     croak "Not testing.  You must declare output with a test function first."
  297.     unless $testing;
  298.  
  299.     # okay, reconnect the test suite back to the saved handles
  300.     $t->output($original_output_handle);
  301.     $t->failure_output($original_failure_handle);
  302.     $t->todo_output($original_todo_handle);
  303.  
  304.     # restore the test no, etc, back to the original point
  305.     $t->current_test($testing_num);
  306.     $testing = 0;
  307.  
  308.     # check the output we've stashed
  309.     unless ($t->ok(($out->check && $err->check), $mess))
  310.     {
  311.       # print out the diagnostic information about why this
  312.       # test failed
  313.  
  314.       local $_;
  315.  
  316.       $t->diag(map {"$_\n"} $out->complaint)
  317.     unless $out->check;
  318.  
  319.       $t->diag(map {"$_\n"} $err->complaint)
  320.     unless $err->check;
  321.     }
  322. }
  323.  
  324. =item line_num
  325.  
  326. A utility function that returns the line number that the function was
  327. called on.  You can pass it an offset which will be added to the
  328. result.  This is very useful for working out the correct text of
  329. diagnostic methods that contain line numbers.
  330.  
  331. Essentially this is the same as the C<__LINE__> macro, but the
  332. C<line_num(+3)> idiom is arguably nicer.
  333.  
  334. =cut
  335.  
  336. sub line_num
  337. {
  338.     my ($package, $filename, $line) = caller;
  339.     return $line + (shift() || 0); # prevent warnings
  340. }
  341.  
  342. =back
  343.  
  344. In addition to the six exported functions there there exists one
  345. function that can only be accessed with a fully qualified function
  346. call.
  347.  
  348. =over 4
  349.  
  350. =item color
  351.  
  352. When C<test_test> is called and the output that your tests generate
  353. does not match that which you declared, C<test_test> will print out
  354. debug information showing the two conflicting versions.  As this
  355. output itself is debug information it can be confusing which part of
  356. the output is from C<test_test> and which was the original output from
  357. your original tests.  Also, it may be hard to spot things like
  358. extraneous whitespace at the end of lines that may cause your test to
  359. fail even though the output looks similar.
  360.  
  361. To assist you, if you have the B<Term::ANSIColor> module installed
  362. (which you should do by default from perl 5.005 onwards), C<test_test>
  363. can colour the background of the debug information to disambiguate the
  364. different types of output. The debug output will have it's background
  365. coloured green and red.  The green part represents the text which is
  366. the same between the executed and actual output, the red shows which
  367. part differs.
  368.  
  369. The C<color> function determines if colouring should occur or not.
  370. Passing it a true or false value will enable or disable colouring
  371. respectively, and the function called with no argument will return the
  372. current setting.
  373.  
  374. To enable colouring from the command line, you can use the
  375. B<Text::Builder::Tester::Color> module like so:
  376.  
  377.    perl -Mlib=Text::Builder::Tester::Color test.t
  378.  
  379. Or by including the B<Test::Builder::Tester::Color> module directly in
  380. the PERL5LIB.
  381.  
  382. =cut
  383.  
  384. my $color;
  385. sub color
  386. {
  387.   $color = shift if @_;
  388.   $color;
  389. }
  390.  
  391. =back
  392.  
  393. =head1 BUGS
  394.  
  395. Calls B<Test::Builder>'s C<no_ending> method turning off the ending
  396. tests.  This is needed as otherwise it will trip out because we've run
  397. more tests than we strictly should have and it'll register any
  398. failures we had that we were testing for as real failures.
  399.  
  400. The color function doesn't work unless B<Term::ANSIColor> is installed
  401. and is compatible with your terminal.
  402.  
  403. Bugs (and requests for new features) can be reported to the author
  404. though the CPAN RT system:
  405. L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Builder-Tester>
  406.  
  407. =head1 AUTHOR
  408.  
  409. Copyright Mark Fowler E<lt>mark@twoshortplanks.comE<gt> 2002.
  410.  
  411. Some code taken from B<Test::More> and B<Test::Catch>, written by by
  412. Michael G Schwern E<lt>schwern@pobox.comE<gt>.  Hence, those parts
  413. Copyright Micheal G Schwern 2001.  Used and distributed with
  414. permission.
  415.  
  416. This program is free software; you can redistribute it
  417. and/or modify it under the same terms as Perl itself.
  418.  
  419. =head1 NOTES
  420.  
  421. This code has been tested explicitly on the following versions
  422. of perl: 5.7.3, 5.6.1, 5.6.0, 5.005_03, 5.004_05 and 5.004.
  423.  
  424. Thanks to Richard Clamp E<lt>richardc@unixbeard.netE<gt> for letting
  425. me use his testing system to try this module out on.
  426.  
  427. =head1 SEE ALSO
  428.  
  429. L<Test::Builder>, L<Test::Builder::Tester::Color>, L<Test::More>.
  430.  
  431. =cut
  432.  
  433. 1;
  434.  
  435. ####################################################################
  436. # Helper class that is used to remember expected and received data
  437.  
  438. package Test::Tester::Tie;
  439.  
  440. ##
  441. # add line(s) to be expected
  442.  
  443. sub expect
  444. {
  445.     my $self = shift;
  446.     $self->[2] .= join '', map { "$_\n" } @_;
  447. }
  448.  
  449. ##
  450. # return true iff the expected data matches the got data
  451.  
  452. sub check
  453. {
  454.     my $self = shift;
  455.  
  456.     # turn off warnings as these might be undef
  457.     local $^W = 0;
  458.  
  459.     $self->[1] eq $self->[2];
  460. }
  461.  
  462. ##
  463. # a complaint message about the inputs not matching (to be
  464. # used for debugging messages)
  465.  
  466. sub complaint
  467. {
  468.     my $self = shift;
  469.     my ($type, $got, $wanted) = @$self;
  470.  
  471.     # are we running in colour mode?
  472.     if (Test::Builder::Tester::color)
  473.     {
  474.       # get color
  475.       eval "require Term::ANSIColor";
  476.       unless ($@)
  477.       {
  478.     # colours
  479.  
  480.     my $green = Term::ANSIColor::color("black").
  481.                 Term::ANSIColor::color("on_green");
  482.         my $red   = Term::ANSIColor::color("black").
  483.                     Term::ANSIColor::color("on_red");
  484.     my $reset = Term::ANSIColor::color("reset");
  485.  
  486.     # work out where the two strings start to differ
  487.     my $char = 0;
  488.     $char++ while substr($got, $char, 1) eq substr($wanted, $char, 1);
  489.  
  490.     # get the start string and the two end strings
  491.     my $start     = $green . substr($wanted, 0,   $char);
  492.     my $gotend    = $red   . substr($got   , $char) . $reset;
  493.     my $wantedend = $red   . substr($wanted, $char) . $reset;
  494.  
  495.     # make the start turn green on and off
  496.     $start =~ s/\n/$reset\n$green/g;
  497.  
  498.     # make the ends turn red on and off
  499.     $gotend    =~ s/\n/$reset\n$red/g;
  500.     $wantedend =~ s/\n/$reset\n$red/g;
  501.  
  502.     # rebuild the strings
  503.     $got    = $start . $gotend;
  504.     $wanted = $start . $wantedend;
  505.       }
  506.     }
  507.  
  508.     return "$type is:\n" .
  509.            "$got\nnot:\n$wanted\nas expected"
  510. }
  511.  
  512. ##
  513. # forget all expected and got data
  514.  
  515. sub reset
  516. {
  517.     my $self = shift;
  518.     @$self = ($self->[0]);
  519. }
  520.  
  521. ###
  522. # tie interface
  523. ###
  524.  
  525. sub PRINT  {
  526.     my $self = shift;
  527.     $self->[1] .= join '', @_;
  528. }
  529.  
  530. sub TIEHANDLE {
  531.     my $class = shift;
  532.     my $self = [shift()];
  533.     return bless $self, $class;
  534. }
  535.  
  536. sub READ {}
  537. sub READLINE {}
  538. sub GETC {}
  539. sub FILENO {}
  540.  
  541. 1;
  542.