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