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