xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Simple/lib/Test/Builder/Tester.pm (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
1b39c5158Smillertpackage Test::Builder::Tester;
2b39c5158Smillert
3b39c5158Smillertuse strict;
4*3d61058aSafresh1our $VERSION = '1.302199';
5b39c5158Smillert
69f11ffb7Safresh1use Test::Builder;
7b39c5158Smillertuse Symbol;
8b39c5158Smillertuse Carp;
9b39c5158Smillert
10b39c5158Smillert=head1 NAME
11b39c5158Smillert
12b39c5158SmillertTest::Builder::Tester - test testsuites that have been built with
13b39c5158SmillertTest::Builder
14b39c5158Smillert
15b39c5158Smillert=head1 SYNOPSIS
16b39c5158Smillert
17b39c5158Smillert    use Test::Builder::Tester tests => 1;
18b39c5158Smillert    use Test::More;
19b39c5158Smillert
20b39c5158Smillert    test_out("not ok 1 - foo");
21b39c5158Smillert    test_fail(+1);
22b39c5158Smillert    fail("foo");
23b39c5158Smillert    test_test("fail works");
24b39c5158Smillert
25b39c5158Smillert=head1 DESCRIPTION
26b39c5158Smillert
27b39c5158SmillertA module that helps you test testing modules that are built with
28b8851fccSafresh1L<Test::Builder>.
29b39c5158Smillert
30b39c5158SmillertThe testing system is designed to be used by performing a three step
31b39c5158Smillertprocess for each test you wish to test.  This process starts with using
32b39c5158SmillertC<test_out> and C<test_err> in advance to declare what the testsuite you
33b8851fccSafresh1are testing will output with L<Test::Builder> to stdout and stderr.
34b39c5158Smillert
35b39c5158SmillertYou then can run the test(s) from your test suite that call
36b8851fccSafresh1L<Test::Builder>.  At this point the output of L<Test::Builder> is
37b8851fccSafresh1safely captured by L<Test::Builder::Tester> rather than being
38b39c5158Smillertinterpreted as real test output.
39b39c5158Smillert
40b39c5158SmillertThe final stage is to call C<test_test> that will simply compare what you
41b8851fccSafresh1predeclared to what L<Test::Builder> actually outputted, and report the
42b39c5158Smillertresults back with a "ok" or "not ok" (with debugging) to the normal
43b39c5158Smillertoutput.
44b39c5158Smillert
45b39c5158Smillert=cut
46b39c5158Smillert
47b39c5158Smillert####
48b39c5158Smillert# set up testing
49b39c5158Smillert####
50b39c5158Smillert
51b39c5158Smillertmy $t = Test::Builder->new;
52b39c5158Smillert
53b39c5158Smillert###
54b39c5158Smillert# make us an exporter
55b39c5158Smillert###
56b39c5158Smillert
57b39c5158Smillertuse Exporter;
58b39c5158Smillertour @ISA = qw(Exporter);
59b39c5158Smillert
60b39c5158Smillertour @EXPORT = qw(test_out test_err test_fail test_diag test_test line_num);
61b39c5158Smillert
62b39c5158Smillertsub import {
63b39c5158Smillert    my $class = shift;
64b39c5158Smillert    my(@plan) = @_;
65b39c5158Smillert
66b39c5158Smillert    my $caller = caller;
67b39c5158Smillert
68b39c5158Smillert    $t->exported_to($caller);
69b39c5158Smillert    $t->plan(@plan);
70b39c5158Smillert
71b39c5158Smillert    my @imports = ();
72b39c5158Smillert    foreach my $idx ( 0 .. $#plan ) {
73b39c5158Smillert        if( $plan[$idx] eq 'import' ) {
74b39c5158Smillert            @imports = @{ $plan[ $idx + 1 ] };
75b39c5158Smillert            last;
76b39c5158Smillert        }
77b39c5158Smillert    }
78b39c5158Smillert
79b39c5158Smillert    __PACKAGE__->export_to_level( 1, __PACKAGE__, @imports );
80b39c5158Smillert}
81b39c5158Smillert
82b39c5158Smillert###
83b39c5158Smillert# set up file handles
84b39c5158Smillert###
85b39c5158Smillert
86b39c5158Smillert# create some private file handles
87b39c5158Smillertmy $output_handle = gensym;
88b39c5158Smillertmy $error_handle  = gensym;
89b39c5158Smillert
90b39c5158Smillert# and tie them to this package
91b39c5158Smillertmy $out = tie *$output_handle, "Test::Builder::Tester::Tie", "STDOUT";
92b39c5158Smillertmy $err = tie *$error_handle,  "Test::Builder::Tester::Tie", "STDERR";
93b39c5158Smillert
94b39c5158Smillert####
95b39c5158Smillert# exported functions
96b39c5158Smillert####
97b39c5158Smillert
98b39c5158Smillert# for remembering that we're testing and where we're testing at
99b39c5158Smillertmy $testing = 0;
100b39c5158Smillertmy $testing_num;
101e5157e49Safresh1my $original_is_passing;
102b39c5158Smillert
103b39c5158Smillert# remembering where the file handles were originally connected
104b39c5158Smillertmy $original_output_handle;
105b39c5158Smillertmy $original_failure_handle;
106b39c5158Smillertmy $original_todo_handle;
1079f11ffb7Safresh1my $original_formatter;
108b39c5158Smillert
109b39c5158Smillertmy $original_harness_env;
110b39c5158Smillert
111b39c5158Smillert# function that starts testing and redirects the filehandles for now
112b39c5158Smillertsub _start_testing {
1139f11ffb7Safresh1    # Hack for things that conditioned on Test-Stream being loaded
1149f11ffb7Safresh1    $INC{'Test/Stream.pm'} ||= 'fake' if $INC{'Test/Moose/More.pm'};
115b39c5158Smillert    # even if we're running under Test::Harness pretend we're not
116b39c5158Smillert    # for now.  This needed so Test::Builder doesn't add extra spaces
117b39c5158Smillert    $original_harness_env = $ENV{HARNESS_ACTIVE} || 0;
118b39c5158Smillert    $ENV{HARNESS_ACTIVE} = 0;
119b39c5158Smillert
1209f11ffb7Safresh1    my $hub = $t->{Hub} || ($t->{Stack} ? $t->{Stack}->top : Test2::API::test2_stack->top);
1219f11ffb7Safresh1    $original_formatter = $hub->format;
1229f11ffb7Safresh1    unless ($original_formatter && $original_formatter->isa('Test::Builder::Formatter')) {
1239f11ffb7Safresh1        my $fmt = Test::Builder::Formatter->new;
1249f11ffb7Safresh1        $hub->format($fmt);
1259f11ffb7Safresh1    }
1269f11ffb7Safresh1
127b39c5158Smillert    # remember what the handles were set to
128b39c5158Smillert    $original_output_handle  = $t->output();
129b39c5158Smillert    $original_failure_handle = $t->failure_output();
130b39c5158Smillert    $original_todo_handle    = $t->todo_output();
131b39c5158Smillert
132b39c5158Smillert    # switch out to our own handles
133b39c5158Smillert    $t->output($output_handle);
134b39c5158Smillert    $t->failure_output($error_handle);
13565d9bffcSjasper    $t->todo_output($output_handle);
136b39c5158Smillert
137b39c5158Smillert    # clear the expected list
138b39c5158Smillert    $out->reset();
139b39c5158Smillert    $err->reset();
140b39c5158Smillert
14165d9bffcSjasper    # remember that we're testing
142b39c5158Smillert    $testing     = 1;
143b39c5158Smillert    $testing_num = $t->current_test;
144b39c5158Smillert    $t->current_test(0);
145e5157e49Safresh1    $original_is_passing  = $t->is_passing;
146e5157e49Safresh1    $t->is_passing(1);
147b39c5158Smillert
148b39c5158Smillert    # look, we shouldn't do the ending stuff
149b39c5158Smillert    $t->no_ending(1);
150b39c5158Smillert}
151b39c5158Smillert
152b39c5158Smillert=head2 Functions
153b39c5158Smillert
154b39c5158SmillertThese are the six methods that are exported as default.
155b39c5158Smillert
156b39c5158Smillert=over 4
157b39c5158Smillert
158b39c5158Smillert=item test_out
159b39c5158Smillert
160b39c5158Smillert=item test_err
161b39c5158Smillert
162b39c5158SmillertProcedures for predeclaring the output that your test suite is
163b39c5158Smillertexpected to produce until C<test_test> is called.  These procedures
164b39c5158Smillertautomatically assume that each line terminates with "\n".  So
165b39c5158Smillert
166b39c5158Smillert   test_out("ok 1","ok 2");
167b39c5158Smillert
168b39c5158Smillertis the same as
169b39c5158Smillert
170b39c5158Smillert   test_out("ok 1\nok 2");
171b39c5158Smillert
172b39c5158Smillertwhich is even the same as
173b39c5158Smillert
174b39c5158Smillert   test_out("ok 1");
175b39c5158Smillert   test_out("ok 2");
176b39c5158Smillert
177b39c5158SmillertOnce C<test_out> or C<test_err> (or C<test_fail> or C<test_diag>) have
178b8851fccSafresh1been called, all further output from L<Test::Builder> will be
179b8851fccSafresh1captured by L<Test::Builder::Tester>.  This means that you will not
180b39c5158Smillertbe able perform further tests to the normal output in the normal way
181b39c5158Smillertuntil you call C<test_test> (well, unless you manually meddle with the
182b39c5158Smillertoutput filehandles)
183b39c5158Smillert
184b39c5158Smillert=cut
185b39c5158Smillert
186b39c5158Smillertsub test_out {
187b39c5158Smillert    # do we need to do any setup?
188b39c5158Smillert    _start_testing() unless $testing;
189b39c5158Smillert
190b39c5158Smillert    $out->expect(@_);
191b39c5158Smillert}
192b39c5158Smillert
193b39c5158Smillertsub test_err {
194b39c5158Smillert    # do we need to do any setup?
195b39c5158Smillert    _start_testing() unless $testing;
196b39c5158Smillert
197b39c5158Smillert    $err->expect(@_);
198b39c5158Smillert}
199b39c5158Smillert
200b39c5158Smillert=item test_fail
201b39c5158Smillert
202b8851fccSafresh1Because the standard failure message that L<Test::Builder> produces
203b39c5158Smillertwhenever a test fails will be a common occurrence in your test error
20465d9bffcSjasperoutput, and because it has changed between Test::Builder versions, rather
205b39c5158Smillertthan forcing you to call C<test_err> with the string all the time like
206b39c5158Smillertso
207b39c5158Smillert
208b39c5158Smillert    test_err("# Failed test ($0 at line ".line_num(+1).")");
209b39c5158Smillert
210b39c5158SmillertC<test_fail> exists as a convenience function that can be called
211b39c5158Smillertinstead.  It takes one argument, the offset from the current line that
212b39c5158Smillertthe line that causes the fail is on.
213b39c5158Smillert
214b39c5158Smillert    test_fail(+1);
215b39c5158Smillert
216b39c5158SmillertThis means that the example in the synopsis could be rewritten
217b39c5158Smillertmore simply as:
218b39c5158Smillert
219b39c5158Smillert   test_out("not ok 1 - foo");
220b39c5158Smillert   test_fail(+1);
221b39c5158Smillert   fail("foo");
222b39c5158Smillert   test_test("fail works");
223b39c5158Smillert
224b39c5158Smillert=cut
225b39c5158Smillert
226b39c5158Smillertsub test_fail {
227b39c5158Smillert    # do we need to do any setup?
228b39c5158Smillert    _start_testing() unless $testing;
229b39c5158Smillert
230b39c5158Smillert    # work out what line we should be on
231b39c5158Smillert    my( $package, $filename, $line ) = caller;
232b39c5158Smillert    $line = $line + ( shift() || 0 );    # prevent warnings
233b39c5158Smillert
234b39c5158Smillert    # expect that on stderr
235e5157e49Safresh1    $err->expect("#     Failed test ($filename at line $line)");
236b39c5158Smillert}
237b39c5158Smillert
238b39c5158Smillert=item test_diag
239b39c5158Smillert
240b39c5158SmillertAs most of the remaining expected output to the error stream will be
241b8851fccSafresh1created by L<Test::Builder>'s C<diag> function, L<Test::Builder::Tester>
24265d9bffcSjasperprovides a convenience function C<test_diag> that you can use instead of
243b39c5158SmillertC<test_err>.
244b39c5158Smillert
245b39c5158SmillertThe C<test_diag> function prepends comment hashes and spacing to the
246b39c5158Smillertstart and newlines to the end of the expected output passed to it and
247b39c5158Smillertadds it to the list of expected error output.  So, instead of writing
248b39c5158Smillert
249b39c5158Smillert   test_err("# Couldn't open file");
250b39c5158Smillert
251b39c5158Smillertyou can write
252b39c5158Smillert
253b39c5158Smillert   test_diag("Couldn't open file");
254b39c5158Smillert
255b8851fccSafresh1Remember that L<Test::Builder>'s diag function will not add newlines to
256b39c5158Smillertthe end of output and test_diag will. So to check
257b39c5158Smillert
258b39c5158Smillert   Test::Builder->new->diag("foo\n","bar\n");
259b39c5158Smillert
260b39c5158SmillertYou would do
261b39c5158Smillert
262b39c5158Smillert  test_diag("foo","bar")
263b39c5158Smillert
264b39c5158Smillertwithout the newlines.
265b39c5158Smillert
266b39c5158Smillert=cut
267b39c5158Smillert
268b39c5158Smillertsub test_diag {
269b39c5158Smillert    # do we need to do any setup?
270b39c5158Smillert    _start_testing() unless $testing;
271b39c5158Smillert
272b39c5158Smillert    # expect the same thing, but prepended with "#     "
273b39c5158Smillert    local $_;
274b39c5158Smillert    $err->expect( map { "# $_" } @_ );
275b39c5158Smillert}
276b39c5158Smillert
277b39c5158Smillert=item test_test
278b39c5158Smillert
279b39c5158SmillertActually performs the output check testing the tests, comparing the
280b8851fccSafresh1data (with C<eq>) that we have captured from L<Test::Builder> against
281e5157e49Safresh1what was declared with C<test_out> and C<test_err>.
282b39c5158Smillert
283b39c5158SmillertThis takes name/value pairs that effect how the test is run.
284b39c5158Smillert
285b39c5158Smillert=over
286b39c5158Smillert
287b39c5158Smillert=item title (synonym 'name', 'label')
288b39c5158Smillert
289b39c5158SmillertThe name of the test that will be displayed after the C<ok> or C<not
290b39c5158Smillertok>.
291b39c5158Smillert
292b39c5158Smillert=item skip_out
293b39c5158Smillert
294b39c5158SmillertSetting this to a true value will cause the test to ignore if the
295b39c5158Smillertoutput sent by the test to the output stream does not match that
296b39c5158Smillertdeclared with C<test_out>.
297b39c5158Smillert
298b39c5158Smillert=item skip_err
299b39c5158Smillert
300b39c5158SmillertSetting this to a true value will cause the test to ignore if the
301b39c5158Smillertoutput sent by the test to the error stream does not match that
302b39c5158Smillertdeclared with C<test_err>.
303b39c5158Smillert
304b39c5158Smillert=back
305b39c5158Smillert
30665d9bffcSjasperAs a convenience, if only one argument is passed then this argument
307b39c5158Smillertis assumed to be the name of the test (as in the above examples.)
308b39c5158Smillert
309b39c5158SmillertOnce C<test_test> has been run test output will be redirected back to
310b8851fccSafresh1the original filehandles that L<Test::Builder> was connected to
311b39c5158Smillert(probably STDOUT and STDERR,) meaning any further tests you run
312b8851fccSafresh1will function normally and cause success/errors for L<Test::Harness>.
313b39c5158Smillert
314b39c5158Smillert=cut
315b39c5158Smillert
316b39c5158Smillertsub test_test {
3179f11ffb7Safresh1    # END the hack
3189f11ffb7Safresh1    delete $INC{'Test/Stream.pm'} if $INC{'Test/Stream.pm'} && $INC{'Test/Stream.pm'} eq 'fake';
31965d9bffcSjasper    # decode the arguments as described in the pod
320b39c5158Smillert    my $mess;
321b39c5158Smillert    my %args;
322b39c5158Smillert    if( @_ == 1 ) {
323b39c5158Smillert        $mess = shift
324b39c5158Smillert    }
325b39c5158Smillert    else {
326b39c5158Smillert        %args = @_;
327b39c5158Smillert        $mess = $args{name} if exists( $args{name} );
328b39c5158Smillert        $mess = $args{title} if exists( $args{title} );
329b39c5158Smillert        $mess = $args{label} if exists( $args{label} );
330b39c5158Smillert    }
331b39c5158Smillert
332b39c5158Smillert    # er, are we testing?
333b39c5158Smillert    croak "Not testing.  You must declare output with a test function first."
334b39c5158Smillert      unless $testing;
335b39c5158Smillert
3369f11ffb7Safresh1
3379f11ffb7Safresh1    my $hub = $t->{Hub} || Test2::API::test2_stack->top;
3389f11ffb7Safresh1    $hub->format($original_formatter);
3399f11ffb7Safresh1
340b39c5158Smillert    # okay, reconnect the test suite back to the saved handles
341b39c5158Smillert    $t->output($original_output_handle);
342b39c5158Smillert    $t->failure_output($original_failure_handle);
343b39c5158Smillert    $t->todo_output($original_todo_handle);
344b39c5158Smillert
345b39c5158Smillert    # restore the test no, etc, back to the original point
346b39c5158Smillert    $t->current_test($testing_num);
347b39c5158Smillert    $testing = 0;
348e5157e49Safresh1    $t->is_passing($original_is_passing);
349b39c5158Smillert
350b39c5158Smillert    # re-enable the original setting of the harness
351b39c5158Smillert    $ENV{HARNESS_ACTIVE} = $original_harness_env;
352b39c5158Smillert
353b39c5158Smillert    # check the output we've stashed
354b39c5158Smillert    unless( $t->ok( ( $args{skip_out} || $out->check ) &&
355b39c5158Smillert                    ( $args{skip_err} || $err->check ), $mess )
356b39c5158Smillert    )
357b39c5158Smillert    {
358b39c5158Smillert        # print out the diagnostic information about why this
359b39c5158Smillert        # test failed
360b39c5158Smillert
361b39c5158Smillert        local $_;
362b39c5158Smillert
363b39c5158Smillert        $t->diag( map { "$_\n" } $out->complaint )
364b39c5158Smillert          unless $args{skip_out} || $out->check;
365b39c5158Smillert
366b39c5158Smillert        $t->diag( map { "$_\n" } $err->complaint )
367b39c5158Smillert          unless $args{skip_err} || $err->check;
368b39c5158Smillert    }
369b39c5158Smillert}
370b39c5158Smillert
371b39c5158Smillert=item line_num
372b39c5158Smillert
373b39c5158SmillertA utility function that returns the line number that the function was
374b39c5158Smillertcalled on.  You can pass it an offset which will be added to the
375b39c5158Smillertresult.  This is very useful for working out the correct text of
376b39c5158Smillertdiagnostic functions that contain line numbers.
377b39c5158Smillert
378b39c5158SmillertEssentially this is the same as the C<__LINE__> macro, but the
379b39c5158SmillertC<line_num(+3)> idiom is arguably nicer.
380b39c5158Smillert
381b39c5158Smillert=cut
382b39c5158Smillert
383b39c5158Smillertsub line_num {
384b39c5158Smillert    my( $package, $filename, $line ) = caller;
385b39c5158Smillert    return $line + ( shift() || 0 );    # prevent warnings
386b39c5158Smillert}
387b39c5158Smillert
388b39c5158Smillert=back
389b39c5158Smillert
39065d9bffcSjasperIn addition to the six exported functions there exists one
391b39c5158Smillertfunction that can only be accessed with a fully qualified function
392b39c5158Smillertcall.
393b39c5158Smillert
394b39c5158Smillert=over 4
395b39c5158Smillert
396b39c5158Smillert=item color
397b39c5158Smillert
398b39c5158SmillertWhen C<test_test> is called and the output that your tests generate
399b39c5158Smillertdoes not match that which you declared, C<test_test> will print out
400b39c5158Smillertdebug information showing the two conflicting versions.  As this
401b39c5158Smillertoutput itself is debug information it can be confusing which part of
402b39c5158Smillertthe output is from C<test_test> and which was the original output from
403b39c5158Smillertyour original tests.  Also, it may be hard to spot things like
404b39c5158Smillertextraneous whitespace at the end of lines that may cause your test to
405b39c5158Smillertfail even though the output looks similar.
406b39c5158Smillert
407b39c5158SmillertTo assist you C<test_test> can colour the background of the debug
408b39c5158Smillertinformation to disambiguate the different types of output. The debug
40965d9bffcSjasperoutput will have its background coloured green and red.  The green
410b39c5158Smillertpart represents the text which is the same between the executed and
411b39c5158Smillertactual output, the red shows which part differs.
412b39c5158Smillert
413b39c5158SmillertThe C<color> function determines if colouring should occur or not.
414b39c5158SmillertPassing it a true or false value will enable or disable colouring
415b39c5158Smillertrespectively, and the function called with no argument will return the
416b39c5158Smillertcurrent setting.
417b39c5158Smillert
418b39c5158SmillertTo enable colouring from the command line, you can use the
419b8851fccSafresh1L<Text::Builder::Tester::Color> module like so:
420b39c5158Smillert
421b39c5158Smillert   perl -Mlib=Text::Builder::Tester::Color test.t
422b39c5158Smillert
423b8851fccSafresh1Or by including the L<Test::Builder::Tester::Color> module directly in
424b39c5158Smillertthe PERL5LIB.
425b39c5158Smillert
426b39c5158Smillert=cut
427b39c5158Smillert
428b39c5158Smillertmy $color;
429b39c5158Smillert
430b39c5158Smillertsub color {
431b39c5158Smillert    $color = shift if @_;
432b39c5158Smillert    $color;
433b39c5158Smillert}
434b39c5158Smillert
435b39c5158Smillert=back
436b39c5158Smillert
437b39c5158Smillert=head1 BUGS
438b39c5158Smillert
4399f11ffb7Safresh1Test::Builder::Tester does not handle plans well. It has never done anything
4409f11ffb7Safresh1special with plans. This means that plans from outside Test::Builder::Tester
4419f11ffb7Safresh1will effect Test::Builder::Tester, worse plans when using Test::Builder::Tester
4429f11ffb7Safresh1will effect overall testing. At this point there are no plans to fix this bug
4439f11ffb7Safresh1as people have come to depend on it, and Test::Builder::Tester is now
4449f11ffb7Safresh1discouraged in favor of C<Test2::API::intercept()>. See
4459f11ffb7Safresh1L<https://github.com/Test-More/test-more/issues/667>
4469f11ffb7Safresh1
447b39c5158SmillertCalls C<< Test::Builder->no_ending >> turning off the ending tests.
448b39c5158SmillertThis is needed as otherwise it will trip out because we've run more
449b39c5158Smillerttests than we strictly should have and it'll register any failures we
450b39c5158Smillerthad that we were testing for as real failures.
451b39c5158Smillert
452b8851fccSafresh1The color function doesn't work unless L<Term::ANSIColor> is
4539f11ffb7Safresh1compatible with your terminal. Additionally, L<Win32::Console::ANSI>
4549f11ffb7Safresh1must be installed on windows platforms for color output.
455b39c5158Smillert
456b39c5158SmillertBugs (and requests for new features) can be reported to the author
4579f11ffb7Safresh1though GitHub:
4589f11ffb7Safresh1L<https://github.com/Test-More/test-more/issues>
459b39c5158Smillert
460b39c5158Smillert=head1 AUTHOR
461b39c5158Smillert
462b39c5158SmillertCopyright Mark Fowler E<lt>mark@twoshortplanks.comE<gt> 2002, 2004.
463b39c5158Smillert
464b8851fccSafresh1Some code taken from L<Test::More> and L<Test::Catch>, written by
465b39c5158SmillertMichael G Schwern E<lt>schwern@pobox.comE<gt>.  Hence, those parts
466b39c5158SmillertCopyright Micheal G Schwern 2001.  Used and distributed with
467b39c5158Smillertpermission.
468b39c5158Smillert
469b39c5158SmillertThis program is free software; you can redistribute it
470b39c5158Smillertand/or modify it under the same terms as Perl itself.
471b39c5158Smillert
472b8851fccSafresh1=head1 MAINTAINERS
473b8851fccSafresh1
474b8851fccSafresh1=over 4
475b8851fccSafresh1
476b8851fccSafresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
477b8851fccSafresh1
478b8851fccSafresh1=back
479b8851fccSafresh1
480b39c5158Smillert=head1 NOTES
481b39c5158Smillert
482b39c5158SmillertThanks to Richard Clamp E<lt>richardc@unixbeard.netE<gt> for letting
483b39c5158Smillertme use his testing system to try this module out on.
484b39c5158Smillert
485b39c5158Smillert=head1 SEE ALSO
486b39c5158Smillert
487b39c5158SmillertL<Test::Builder>, L<Test::Builder::Tester::Color>, L<Test::More>.
488b39c5158Smillert
489b39c5158Smillert=cut
490b39c5158Smillert
491b39c5158Smillert1;
492b39c5158Smillert
493b39c5158Smillert####################################################################
494b39c5158Smillert# Helper class that is used to remember expected and received data
495b39c5158Smillert
496b39c5158Smillertpackage Test::Builder::Tester::Tie;
497b39c5158Smillert
498b39c5158Smillert##
499b39c5158Smillert# add line(s) to be expected
500b39c5158Smillert
501b39c5158Smillertsub expect {
502b39c5158Smillert    my $self = shift;
503b39c5158Smillert
504b39c5158Smillert    my @checks = @_;
505b39c5158Smillert    foreach my $check (@checks) {
506e5157e49Safresh1        $check = $self->_account_for_subtest($check);
507b39c5158Smillert        $check = $self->_translate_Failed_check($check);
508b39c5158Smillert        push @{ $self->{wanted} }, ref $check ? $check : "$check\n";
509b39c5158Smillert    }
510b39c5158Smillert}
511b39c5158Smillert
512e5157e49Safresh1sub _account_for_subtest {
513e5157e49Safresh1    my( $self, $check ) = @_;
514e5157e49Safresh1
5159f11ffb7Safresh1    my $hub = $t->{Stack}->top;
5169f11ffb7Safresh1    my $nesting = $hub->isa('Test2::Hub::Subtest') ? $hub->nested : 0;
5179f11ffb7Safresh1    return ref($check) ? $check : ('    ' x $nesting) . $check;
518e5157e49Safresh1}
519e5157e49Safresh1
520b39c5158Smillertsub _translate_Failed_check {
521b39c5158Smillert    my( $self, $check ) = @_;
522b39c5158Smillert
523b39c5158Smillert    if( $check =~ /\A(.*)#     (Failed .*test) \((.*?) at line (\d+)\)\Z(?!\n)/ ) {
524b39c5158Smillert        $check = "/\Q$1\E#\\s+\Q$2\E.*?\\n?.*?\Qat $3\E line \Q$4\E.*\\n?/";
525b39c5158Smillert    }
526b39c5158Smillert
527b39c5158Smillert    return $check;
528b39c5158Smillert}
529b39c5158Smillert
530b39c5158Smillert##
531b39c5158Smillert# return true iff the expected data matches the got data
532b39c5158Smillert
533b39c5158Smillertsub check {
534b39c5158Smillert    my $self = shift;
535b39c5158Smillert
536b39c5158Smillert    # turn off warnings as these might be undef
537b39c5158Smillert    local $^W = 0;
538b39c5158Smillert
539b39c5158Smillert    my @checks = @{ $self->{wanted} };
540b39c5158Smillert    my $got    = $self->{got};
541b39c5158Smillert    foreach my $check (@checks) {
542b39c5158Smillert        $check = "\Q$check\E" unless( $check =~ s,^/(.*)/$,$1, or ref $check );
543b39c5158Smillert        return 0 unless $got =~ s/^$check//;
544b39c5158Smillert    }
545b39c5158Smillert
546b39c5158Smillert    return length $got == 0;
547b39c5158Smillert}
548b39c5158Smillert
549b39c5158Smillert##
550b39c5158Smillert# a complaint message about the inputs not matching (to be
551b39c5158Smillert# used for debugging messages)
552b39c5158Smillert
553b39c5158Smillertsub complaint {
554b39c5158Smillert    my $self   = shift;
555b39c5158Smillert    my $type   = $self->type;
556b39c5158Smillert    my $got    = $self->got;
557e5157e49Safresh1    my $wanted = join '', @{ $self->wanted };
558b39c5158Smillert
559b39c5158Smillert    # are we running in colour mode?
560b39c5158Smillert    if(Test::Builder::Tester::color) {
561b39c5158Smillert        # get color
562b39c5158Smillert        eval { require Term::ANSIColor };
563b39c5158Smillert        unless($@) {
5649f11ffb7Safresh1            eval { require Win32::Console::ANSI } if 'MSWin32' eq $^O;  # support color on windows platforms
5659f11ffb7Safresh1
566b39c5158Smillert            # colours
567b39c5158Smillert
568b39c5158Smillert            my $green = Term::ANSIColor::color("black") . Term::ANSIColor::color("on_green");
569b39c5158Smillert            my $red   = Term::ANSIColor::color("black") . Term::ANSIColor::color("on_red");
570b39c5158Smillert            my $reset = Term::ANSIColor::color("reset");
571b39c5158Smillert
572b39c5158Smillert            # work out where the two strings start to differ
573b39c5158Smillert            my $char = 0;
574b39c5158Smillert            $char++ while substr( $got, $char, 1 ) eq substr( $wanted, $char, 1 );
575b39c5158Smillert
576b39c5158Smillert            # get the start string and the two end strings
577b39c5158Smillert            my $start = $green . substr( $wanted, 0, $char );
578b39c5158Smillert            my $gotend    = $red . substr( $got,    $char ) . $reset;
579b39c5158Smillert            my $wantedend = $red . substr( $wanted, $char ) . $reset;
580b39c5158Smillert
581b39c5158Smillert            # make the start turn green on and off
582b39c5158Smillert            $start =~ s/\n/$reset\n$green/g;
583b39c5158Smillert
584b39c5158Smillert            # make the ends turn red on and off
585b39c5158Smillert            $gotend    =~ s/\n/$reset\n$red/g;
586b39c5158Smillert            $wantedend =~ s/\n/$reset\n$red/g;
587b39c5158Smillert
588b39c5158Smillert            # rebuild the strings
589b39c5158Smillert            $got    = $start . $gotend;
590b39c5158Smillert            $wanted = $start . $wantedend;
591b39c5158Smillert        }
592b39c5158Smillert    }
593b39c5158Smillert
5949f11ffb7Safresh1    my @got = split "\n", $got;
5959f11ffb7Safresh1    my @wanted = split "\n", $wanted;
5969f11ffb7Safresh1
5979f11ffb7Safresh1    $got = "";
5989f11ffb7Safresh1    $wanted = "";
5999f11ffb7Safresh1
6009f11ffb7Safresh1    while (@got || @wanted) {
6019f11ffb7Safresh1        my $g = shift @got    || "";
6029f11ffb7Safresh1        my $w = shift @wanted || "";
6039f11ffb7Safresh1        if ($g ne $w) {
6049f11ffb7Safresh1            if($g =~ s/(\s+)$/    |> /g) {
6059f11ffb7Safresh1                $g .= ($_ eq ' ' ? '_' : '\t') for split '', $1;
6069f11ffb7Safresh1            }
6079f11ffb7Safresh1            if($w =~ s/(\s+)$/    |> /g) {
6089f11ffb7Safresh1                $w .= ($_ eq ' ' ? '_' : '\t') for split '', $1;
6099f11ffb7Safresh1            }
6109f11ffb7Safresh1            $g = "> $g";
6119f11ffb7Safresh1            $w = "> $w";
6129f11ffb7Safresh1        }
6139f11ffb7Safresh1        else {
6149f11ffb7Safresh1            $g = "  $g";
6159f11ffb7Safresh1            $w = "  $w";
6169f11ffb7Safresh1        }
6179f11ffb7Safresh1        $got = $got ? "$got\n$g" : $g;
6189f11ffb7Safresh1        $wanted = $wanted ? "$wanted\n$w" : $w;
6199f11ffb7Safresh1    }
6209f11ffb7Safresh1
621b39c5158Smillert    return "$type is:\n" . "$got\nnot:\n$wanted\nas expected";
622b39c5158Smillert}
623b39c5158Smillert
624b39c5158Smillert##
625b39c5158Smillert# forget all expected and got data
626b39c5158Smillert
627b39c5158Smillertsub reset {
628b39c5158Smillert    my $self = shift;
629b39c5158Smillert    %$self = (
630b39c5158Smillert        type   => $self->{type},
631b39c5158Smillert        got    => '',
632b39c5158Smillert        wanted => [],
633b39c5158Smillert    );
634b39c5158Smillert}
635b39c5158Smillert
636b39c5158Smillertsub got {
637b39c5158Smillert    my $self = shift;
638b39c5158Smillert    return $self->{got};
639b39c5158Smillert}
640b39c5158Smillert
641b39c5158Smillertsub wanted {
642b39c5158Smillert    my $self = shift;
643b39c5158Smillert    return $self->{wanted};
644b39c5158Smillert}
645b39c5158Smillert
646b39c5158Smillertsub type {
647b39c5158Smillert    my $self = shift;
648b39c5158Smillert    return $self->{type};
649b39c5158Smillert}
650b39c5158Smillert
651b39c5158Smillert###
652b39c5158Smillert# tie interface
653b39c5158Smillert###
654b39c5158Smillert
655b39c5158Smillertsub PRINT {
656b39c5158Smillert    my $self = shift;
657b39c5158Smillert    $self->{got} .= join '', @_;
658b39c5158Smillert}
659b39c5158Smillert
660b39c5158Smillertsub TIEHANDLE {
661b39c5158Smillert    my( $class, $type ) = @_;
662b39c5158Smillert
663b39c5158Smillert    my $self = bless { type => $type }, $class;
664b39c5158Smillert
665b39c5158Smillert    $self->reset;
666b39c5158Smillert
667b39c5158Smillert    return $self;
668b39c5158Smillert}
669b39c5158Smillert
670b39c5158Smillertsub READ     { }
671b39c5158Smillertsub READLINE { }
672b39c5158Smillertsub GETC     { }
673b39c5158Smillertsub FILENO   { }
674b39c5158Smillert
675b39c5158Smillert1;
676