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