#!/usr/bin/perl -w use Test::More tests => 12; use Symbol; use Test::Builder; use Test::Builder::Tester; use strict; # argh! now we need to test the thing we're testing. Basically we need # to pretty much reimplement the whole code again. This is very # annoying but can't be avoided. And onwards with the cut and paste # My brain is melting. My brain is melting. ETOOMANYLAYERSOFTESTING # create some private file handles my $output_handle = gensym; my $error_handle = gensym; # and tie them to this package my $out = tie *$output_handle, "Test::Tester::Tie2", "STDOUT"; my $err = tie *$error_handle, "Test::Tester::Tie2", "STDERR"; # ooooh, use the test suite my $t = Test::Builder->new; # remember the testing outputs my $original_output_handle; my $original_failure_handle; my $original_todo_handle; my $testing_num; sub start_testing { # remember what the handles were set to $original_output_handle = $t->output(); $original_failure_handle = $t->failure_output(); $original_todo_handle = $t->todo_output(); # switch out to our own handles $t->output($output_handle); $t->failure_output($error_handle); $t->todo_output($error_handle); # clear the expected list $out->reset(); $err->reset(); # remeber that we're testing $testing_num = $t->current_test; $t->current_test(0); } # each test test is actually two tests. This is bad and wrong # but makes blood come out of my ears if I don't at least simplify # it a little this way sub my_test_test { my $text = shift; local $^W = 0; # reset the outputs $t->output($original_output_handle); $t->failure_output($original_failure_handle); $t->todo_output($original_todo_handle); # reset the number of tests $t->current_test($testing_num); # check we got the same values my $got; my $wanted; # stdout ($wanted, $got) = $out->both; $t->is_eq($got, $wanted, "STDOUT $text"); # stderr ($got, $wanted) = $err->both; $got =~ s/ /+/g; $wanted =~ s/ /+/g; $t->ok($got eq $wanted, "STDERR $text") or $t->diag("HEY THERE, I GOT '$got' not '$wanted'"); } #################################################################### # Meta meta tests #################################################################### # this is a quick test to check the hack that I've just implemented # actually does a cut down version of Test::Builder::Tester start_testing(); $out->expect("ok 1 - foo"); pass("foo"); my_test_test("basic meta meta test"); start_testing(); $out->expect("not ok 1 - foo"); $err->expect("# Failed test ($0 at line ".line_num(+1).")"); fail("foo"); my_test_test("basic meta meta test 2"); start_testing(); $out->expect("ok 1 - bar"); test_out("ok 1 - foo"); pass("foo"); test_test("bar"); my_test_test("meta meta test with tbt"); start_testing(); $out->expect("ok 1 - bar"); test_out("not ok 1 - foo"); test_err("# Failed test ($0 at line ".line_num(+1).")"); fail("foo"); test_test("bar"); my_test_test("meta meta test with tbt2 "); #################################################################### # Actual meta tests #################################################################### # test that when something doesn't match the expected output we # get the correct error message # turn off colour Test::Builder::Tester::color(0); # declare the colours empty my ($red, $reset, $green) = ("","",""); # set up the outer wrapper again start_testing(); $out->expect("not ok 1 - bar"); $err->expect("# Failed test ($0 at line ".line_num(+24).")"); $err->expect("# STDERR is:", "# ${green}# Failed test ($0 at line ".line_num(+19).")$reset", "# ${green}# got: 'php'$reset", "# ${green}# expected: '${red}Perl'$reset", "# $reset", "# not:", "# ${green}# Failed test ($0 at line ".line_num(+19).")$reset", "# ${green}# got: 'php'$reset", "# ${green}# expected: '${red}perl'$reset", "# $reset", "# as expected"); # set up what the inner wrapper expects (which it won't get); test_out("not ok 1 - foo"); test_err("# Failed test ($0 at line ".line_num(+5).")", "# got: 'php'", "# expected: 'perl'"); # the actual test function that we are testing (which fails) is("php","Perl","foo"); # the test wrapper which will fail in turn as in the diagnostics # from the first fail we get "Perl" where we expected "perl" test_test("bar"); # finally check that we got the correct diagnostics about our # diagnostics failing out my_test_test("meta test b&w"); ############################################ # load the module and get colours if we can eval "require Term::ANSIColor"; unless ($@) { $red = Term::ANSIColor::color("black") . Term::ANSIColor::color("on_red"); $reset = Term::ANSIColor::color("reset"); $green = Term::ANSIColor::color("black"). Term::ANSIColor::color("on_green"); } # turn colour mode on Test::Builder::Tester::color(1); # set up the outer wrapper again start_testing(); $out->expect("not ok 1 - bar"); $err->expect("# Failed test ($0 at line ".line_num(+24).")"); $err->expect("# STDERR is:", "# ${green}# Failed test ($0 at line ".line_num(+19).")$reset", "# ${green}# got: 'php'$reset", "# ${green}# expected: '${red}Perl'$reset", "# ${red}$reset", "# not:", "# ${green}# Failed test ($0 at line ".line_num(+19).")$reset", "# ${green}# got: 'php'$reset", "# ${green}# expected: '${red}perl'$reset", "# ${red}$reset", "# as expected"); # set up what the inner wrapper expects (which it won't get); test_out("not ok 1 - foo"); test_err("# Failed test ($0 at line ".line_num(+5).")", "# got: 'php'", "# expected: 'perl'"); # the actual test function that we are testing (which fails) is("php","Perl","foo"); # the test wrapper which will fail in turn as in the diagnostics # from the first fail we get "Perl" where we expected "perl" test_test("bar"); # finally check that we got the correct diagnostics about our # diagnostics failing out my_test_test("meta test color"); #################################################################### package Test::Tester::Tie2; ## # add line(s) to be expected sub expect { my $self = shift; $self->[2] .= join '', map { "$_\n" } @_; } sub both { my $self = shift; return ($self->[1], $self->[2]); } ## # forget all expected and got data sub reset { my $self = shift; @$self = ($self->[0]); } ### # tie interface ### sub PRINT { my $self = shift; $self->[1] .= join '', @_; } sub TIEHANDLE { my $class = shift; my $self = [shift()]; return bless $self, $class; } sub READ {} sub READLINE {} sub GETC {} sub FILENO {}