1N/Apackage Test::Builder;
1N/A
1N/Ause 5.004;
1N/A
1N/A# $^C was only introduced in 5.005-ish. We do this to prevent
1N/A# use of uninitialized value warnings in older perls.
1N/A$^C ||= 0;
1N/A
1N/Ause strict;
1N/Ause vars qw($VERSION $CLASS);
1N/A$VERSION = '0.17';
1N/A$CLASS = __PACKAGE__;
1N/A
1N/Amy $IsVMS = $^O eq 'VMS';
1N/A
1N/A# Make Test::Builder thread-safe for ithreads.
1N/ABEGIN {
1N/A use Config;
1N/A if( $] >= 5.008 && $Config{useithreads} ) {
1N/A require threads;
1N/A require threads::shared;
1N/A threads::shared->import;
1N/A }
1N/A else {
1N/A *share = sub { 0 };
1N/A *lock = sub { 0 };
1N/A }
1N/A}
1N/A
1N/Ause vars qw($Level);
1N/Amy($Test_Died) = 0;
1N/Amy($Have_Plan) = 0;
1N/Amy $Original_Pid = $$;
1N/Amy $Curr_Test = 0; share($Curr_Test);
1N/Amy @Test_Results = (); share(@Test_Results);
1N/Amy @Test_Details = (); share(@Test_Details);
1N/A
1N/A
1N/A=head1 NAME
1N/A
1N/ATest::Builder - Backend for building test libraries
1N/A
1N/A=head1 SYNOPSIS
1N/A
1N/A package My::Test::Module;
1N/A use Test::Builder;
1N/A require Exporter;
1N/A @ISA = qw(Exporter);
1N/A @EXPORT = qw(ok);
1N/A
1N/A my $Test = Test::Builder->new;
1N/A $Test->output('my_logfile');
1N/A
1N/A sub import {
1N/A my($self) = shift;
1N/A my $pack = caller;
1N/A
1N/A $Test->exported_to($pack);
1N/A $Test->plan(@_);
1N/A
1N/A $self->export_to_level(1, $self, 'ok');
1N/A }
1N/A
1N/A sub ok {
1N/A my($test, $name) = @_;
1N/A
1N/A $Test->ok($test, $name);
1N/A }
1N/A
1N/A
1N/A=head1 DESCRIPTION
1N/A
1N/ATest::Simple and Test::More have proven to be popular testing modules,
1N/Abut they're not always flexible enough. Test::Builder provides the a
1N/Abuilding block upon which to write your own test libraries I<which can
1N/Awork together>.
1N/A
1N/A=head2 Construction
1N/A
1N/A=over 4
1N/A
1N/A=item B<new>
1N/A
1N/A my $Test = Test::Builder->new;
1N/A
1N/AReturns a Test::Builder object representing the current state of the
1N/Atest.
1N/A
1N/ASince you only run one test per program, there is B<one and only one>
1N/ATest::Builder object. No matter how many times you call new(), you're
1N/Agetting the same object. (This is called a singleton).
1N/A
1N/A=cut
1N/A
1N/Amy $Test;
1N/Asub new {
1N/A my($class) = shift;
1N/A $Test ||= bless ['Move along, nothing to see here'], $class;
1N/A return $Test;
1N/A}
1N/A
1N/A=back
1N/A
1N/A=head2 Setting up tests
1N/A
1N/AThese methods are for setting up tests and declaring how many there
1N/Aare. You usually only want to call one of these methods.
1N/A
1N/A=over 4
1N/A
1N/A=item B<exported_to>
1N/A
1N/A my $pack = $Test->exported_to;
1N/A $Test->exported_to($pack);
1N/A
1N/ATells Test::Builder what package you exported your functions to.
1N/AThis is important for getting TODO tests right.
1N/A
1N/A=cut
1N/A
1N/Amy $Exported_To;
1N/Asub exported_to {
1N/A my($self, $pack) = @_;
1N/A
1N/A if( defined $pack ) {
1N/A $Exported_To = $pack;
1N/A }
1N/A return $Exported_To;
1N/A}
1N/A
1N/A=item B<plan>
1N/A
1N/A $Test->plan('no_plan');
1N/A $Test->plan( skip_all => $reason );
1N/A $Test->plan( tests => $num_tests );
1N/A
1N/AA convenient way to set up your tests. Call this and Test::Builder
1N/Awill print the appropriate headers and take the appropriate actions.
1N/A
1N/AIf you call plan(), don't call any of the other methods below.
1N/A
1N/A=cut
1N/A
1N/Asub plan {
1N/A my($self, $cmd, $arg) = @_;
1N/A
1N/A return unless $cmd;
1N/A
1N/A if( $Have_Plan ) {
1N/A die sprintf "You tried to plan twice! Second plan at %s line %d\n",
1N/A ($self->caller)[1,2];
1N/A }
1N/A
1N/A if( $cmd eq 'no_plan' ) {
1N/A $self->no_plan;
1N/A }
1N/A elsif( $cmd eq 'skip_all' ) {
1N/A return $self->skip_all($arg);
1N/A }
1N/A elsif( $cmd eq 'tests' ) {
1N/A if( $arg ) {
1N/A return $self->expected_tests($arg);
1N/A }
1N/A elsif( !defined $arg ) {
1N/A die "Got an undefined number of tests. Looks like you tried to ".
1N/A "say how many tests you plan to run but made a mistake.\n";
1N/A }
1N/A elsif( !$arg ) {
1N/A die "You said to run 0 tests! You've got to run something.\n";
1N/A }
1N/A }
1N/A else {
1N/A require Carp;
1N/A my @args = grep { defined } ($cmd, $arg);
1N/A Carp::croak("plan() doesn't understand @args");
1N/A }
1N/A
1N/A return 1;
1N/A}
1N/A
1N/A=item B<expected_tests>
1N/A
1N/A my $max = $Test->expected_tests;
1N/A $Test->expected_tests($max);
1N/A
1N/AGets/sets the # of tests we expect this test to run and prints out
1N/Athe appropriate headers.
1N/A
1N/A=cut
1N/A
1N/Amy $Expected_Tests = 0;
1N/Asub expected_tests {
1N/A my($self, $max) = @_;
1N/A
1N/A if( defined $max ) {
1N/A $Expected_Tests = $max;
1N/A $Have_Plan = 1;
1N/A
1N/A $self->_print("1..$max\n") unless $self->no_header;
1N/A }
1N/A return $Expected_Tests;
1N/A}
1N/A
1N/A
1N/A=item B<no_plan>
1N/A
1N/A $Test->no_plan;
1N/A
1N/ADeclares that this test will run an indeterminate # of tests.
1N/A
1N/A=cut
1N/A
1N/Amy($No_Plan) = 0;
1N/Asub no_plan {
1N/A $No_Plan = 1;
1N/A $Have_Plan = 1;
1N/A}
1N/A
1N/A=item B<has_plan>
1N/A
1N/A $plan = $Test->has_plan
1N/A
1N/AFind out whether a plan has been defined. $plan is either C<undef> (no plan has been set), C<no_plan> (indeterminate # of tests) or an integer (the number of expected tests).
1N/A
1N/A=cut
1N/A
1N/Asub has_plan {
1N/A return($Expected_Tests) if $Expected_Tests;
1N/A return('no_plan') if $No_Plan;
1N/A return(undef);
1N/A};
1N/A
1N/A
1N/A=item B<skip_all>
1N/A
1N/A $Test->skip_all;
1N/A $Test->skip_all($reason);
1N/A
1N/ASkips all the tests, using the given $reason. Exits immediately with 0.
1N/A
1N/A=cut
1N/A
1N/Amy $Skip_All = 0;
1N/Asub skip_all {
1N/A my($self, $reason) = @_;
1N/A
1N/A my $out = "1..0";
1N/A $out .= " # Skip $reason" if $reason;
1N/A $out .= "\n";
1N/A
1N/A $Skip_All = 1;
1N/A
1N/A $self->_print($out) unless $self->no_header;
1N/A exit(0);
1N/A}
1N/A
1N/A=back
1N/A
1N/A=head2 Running tests
1N/A
1N/AThese actually run the tests, analogous to the functions in
1N/ATest::More.
1N/A
1N/A$name is always optional.
1N/A
1N/A=over 4
1N/A
1N/A=item B<ok>
1N/A
1N/A $Test->ok($test, $name);
1N/A
1N/AYour basic test. Pass if $test is true, fail if $test is false. Just
1N/Alike Test::Simple's ok().
1N/A
1N/A=cut
1N/A
1N/Asub ok {
1N/A my($self, $test, $name) = @_;
1N/A
1N/A # $test might contain an object which we don't want to accidentally
1N/A # store, so we turn it into a boolean.
1N/A $test = $test ? 1 : 0;
1N/A
1N/A unless( $Have_Plan ) {
1N/A require Carp;
1N/A Carp::croak("You tried to run a test without a plan! Gotta have a plan.");
1N/A }
1N/A
1N/A lock $Curr_Test;
1N/A $Curr_Test++;
1N/A
1N/A $self->diag(<<ERR) if defined $name and $name =~ /^[\d\s]+$/;
1N/A You named your test '$name'. You shouldn't use numbers for your test names.
1N/A Very confusing.
1N/AERR
1N/A
1N/A my($pack, $file, $line) = $self->caller;
1N/A
1N/A my $todo = $self->todo($pack);
1N/A
1N/A my $out;
1N/A my $result = {};
1N/A share($result);
1N/A
1N/A unless( $test ) {
1N/A $out .= "not ";
1N/A @$result{ 'ok', 'actual_ok' } = ( ( $todo ? 1 : 0 ), 0 );
1N/A }
1N/A else {
1N/A @$result{ 'ok', 'actual_ok' } = ( 1, $test );
1N/A }
1N/A
1N/A $out .= "ok";
1N/A $out .= " $Curr_Test" if $self->use_numbers;
1N/A
1N/A if( defined $name ) {
1N/A $name =~ s|#|\\#|g; # # in a name can confuse Test::Harness.
1N/A $out .= " - $name";
1N/A $result->{name} = $name;
1N/A }
1N/A else {
1N/A $result->{name} = '';
1N/A }
1N/A
1N/A if( $todo ) {
1N/A my $what_todo = $todo;
1N/A $out .= " # TODO $what_todo";
1N/A $result->{reason} = $what_todo;
1N/A $result->{type} = 'todo';
1N/A }
1N/A else {
1N/A $result->{reason} = '';
1N/A $result->{type} = '';
1N/A }
1N/A
1N/A $Test_Results[$Curr_Test-1] = $result;
1N/A $out .= "\n";
1N/A
1N/A $self->_print($out);
1N/A
1N/A unless( $test ) {
1N/A my $msg = $todo ? "Failed (TODO)" : "Failed";
1N/A $self->diag(" $msg test ($file at line $line)\n");
1N/A }
1N/A
1N/A return $test ? 1 : 0;
1N/A}
1N/A
1N/A=item B<is_eq>
1N/A
1N/A $Test->is_eq($got, $expected, $name);
1N/A
1N/ALike Test::More's is(). Checks if $got eq $expected. This is the
1N/Astring version.
1N/A
1N/A=item B<is_num>
1N/A
1N/A $Test->is_num($got, $expected, $name);
1N/A
1N/ALike Test::More's is(). Checks if $got == $expected. This is the
1N/Anumeric version.
1N/A
1N/A=cut
1N/A
1N/Asub is_eq {
1N/A my($self, $got, $expect, $name) = @_;
1N/A local $Level = $Level + 1;
1N/A
1N/A if( !defined $got || !defined $expect ) {
1N/A # undef only matches undef and nothing else
1N/A my $test = !defined $got && !defined $expect;
1N/A
1N/A $self->ok($test, $name);
1N/A $self->_is_diag($got, 'eq', $expect) unless $test;
1N/A return $test;
1N/A }
1N/A
1N/A return $self->cmp_ok($got, 'eq', $expect, $name);
1N/A}
1N/A
1N/Asub is_num {
1N/A my($self, $got, $expect, $name) = @_;
1N/A local $Level = $Level + 1;
1N/A
1N/A if( !defined $got || !defined $expect ) {
1N/A # undef only matches undef and nothing else
1N/A my $test = !defined $got && !defined $expect;
1N/A
1N/A $self->ok($test, $name);
1N/A $self->_is_diag($got, '==', $expect) unless $test;
1N/A return $test;
1N/A }
1N/A
1N/A return $self->cmp_ok($got, '==', $expect, $name);
1N/A}
1N/A
1N/Asub _is_diag {
1N/A my($self, $got, $type, $expect) = @_;
1N/A
1N/A foreach my $val (\$got, \$expect) {
1N/A if( defined $$val ) {
1N/A if( $type eq 'eq' ) {
1N/A # quote and force string context
1N/A $$val = "'$$val'"
1N/A }
1N/A else {
1N/A # force numeric context
1N/A $$val = $$val+0;
1N/A }
1N/A }
1N/A else {
1N/A $$val = 'undef';
1N/A }
1N/A }
1N/A
1N/A return $self->diag(sprintf <<DIAGNOSTIC, $got, $expect);
1N/A got: %s
1N/A expected: %s
1N/ADIAGNOSTIC
1N/A
1N/A}
1N/A
1N/A=item B<isnt_eq>
1N/A
1N/A $Test->isnt_eq($got, $dont_expect, $name);
1N/A
1N/ALike Test::More's isnt(). Checks if $got ne $dont_expect. This is
1N/Athe string version.
1N/A
1N/A=item B<isnt_num>
1N/A
1N/A $Test->is_num($got, $dont_expect, $name);
1N/A
1N/ALike Test::More's isnt(). Checks if $got ne $dont_expect. This is
1N/Athe numeric version.
1N/A
1N/A=cut
1N/A
1N/Asub isnt_eq {
1N/A my($self, $got, $dont_expect, $name) = @_;
1N/A local $Level = $Level + 1;
1N/A
1N/A if( !defined $got || !defined $dont_expect ) {
1N/A # undef only matches undef and nothing else
1N/A my $test = defined $got || defined $dont_expect;
1N/A
1N/A $self->ok($test, $name);
1N/A $self->_cmp_diag('ne', $got, $dont_expect) unless $test;
1N/A return $test;
1N/A }
1N/A
1N/A return $self->cmp_ok($got, 'ne', $dont_expect, $name);
1N/A}
1N/A
1N/Asub isnt_num {
1N/A my($self, $got, $dont_expect, $name) = @_;
1N/A local $Level = $Level + 1;
1N/A
1N/A if( !defined $got || !defined $dont_expect ) {
1N/A # undef only matches undef and nothing else
1N/A my $test = defined $got || defined $dont_expect;
1N/A
1N/A $self->ok($test, $name);
1N/A $self->_cmp_diag('!=', $got, $dont_expect) unless $test;
1N/A return $test;
1N/A }
1N/A
1N/A return $self->cmp_ok($got, '!=', $dont_expect, $name);
1N/A}
1N/A
1N/A
1N/A=item B<like>
1N/A
1N/A $Test->like($this, qr/$regex/, $name);
1N/A $Test->like($this, '/$regex/', $name);
1N/A
1N/ALike Test::More's like(). Checks if $this matches the given $regex.
1N/A
1N/AYou'll want to avoid qr// if you want your tests to work before 5.005.
1N/A
1N/A=item B<unlike>
1N/A
1N/A $Test->unlike($this, qr/$regex/, $name);
1N/A $Test->unlike($this, '/$regex/', $name);
1N/A
1N/ALike Test::More's unlike(). Checks if $this B<does not match> the
1N/Agiven $regex.
1N/A
1N/A=cut
1N/A
1N/Asub like {
1N/A my($self, $this, $regex, $name) = @_;
1N/A
1N/A local $Level = $Level + 1;
1N/A $self->_regex_ok($this, $regex, '=~', $name);
1N/A}
1N/A
1N/Asub unlike {
1N/A my($self, $this, $regex, $name) = @_;
1N/A
1N/A local $Level = $Level + 1;
1N/A $self->_regex_ok($this, $regex, '!~', $name);
1N/A}
1N/A
1N/A=item B<maybe_regex>
1N/A
1N/A $Test->maybe_regex(qr/$regex/);
1N/A $Test->maybe_regex('/$regex/');
1N/A
1N/AConvenience method for building testing functions that take regular
1N/Aexpressions as arguments, but need to work before perl 5.005.
1N/A
1N/ATakes a quoted regular expression produced by qr//, or a string
1N/Arepresenting a regular expression.
1N/A
1N/AReturns a Perl value which may be used instead of the corresponding
1N/Aregular expression, or undef if it's argument is not recognised.
1N/A
1N/AFor example, a version of like(), sans the useful diagnostic messages,
1N/Acould be written as:
1N/A
1N/A sub laconic_like {
1N/A my ($self, $this, $regex, $name) = @_;
1N/A my $usable_regex = $self->maybe_regex($regex);
1N/A die "expecting regex, found '$regex'\n"
1N/A unless $usable_regex;
1N/A $self->ok($this =~ m/$usable_regex/, $name);
1N/A }
1N/A
1N/A=cut
1N/A
1N/A
1N/Asub maybe_regex {
1N/A my ($self, $regex) = @_;
1N/A my $usable_regex = undef;
1N/A if( ref $regex eq 'Regexp' ) {
1N/A $usable_regex = $regex;
1N/A }
1N/A # Check if it looks like '/foo/'
1N/A elsif( my($re, $opts) = $regex =~ m{^ /(.*)/ (\w*) $ }sx ) {
1N/A $usable_regex = length $opts ? "(?$opts)$re" : $re;
1N/A };
1N/A return($usable_regex)
1N/A};
1N/A
1N/Asub _regex_ok {
1N/A my($self, $this, $regex, $cmp, $name) = @_;
1N/A
1N/A local $Level = $Level + 1;
1N/A
1N/A my $ok = 0;
1N/A my $usable_regex = $self->maybe_regex($regex);
1N/A unless (defined $usable_regex) {
1N/A $ok = $self->ok( 0, $name );
1N/A $self->diag(" '$regex' doesn't look much like a regex to me.");
1N/A return $ok;
1N/A }
1N/A
1N/A {
1N/A local $^W = 0;
1N/A my $test = $this =~ /$usable_regex/ ? 1 : 0;
1N/A $test = !$test if $cmp eq '!~';
1N/A $ok = $self->ok( $test, $name );
1N/A }
1N/A
1N/A unless( $ok ) {
1N/A $this = defined $this ? "'$this'" : 'undef';
1N/A my $match = $cmp eq '=~' ? "doesn't match" : "matches";
1N/A $self->diag(sprintf <<DIAGNOSTIC, $this, $match, $regex);
1N/A %s
1N/A %13s '%s'
1N/ADIAGNOSTIC
1N/A
1N/A }
1N/A
1N/A return $ok;
1N/A}
1N/A
1N/A=item B<cmp_ok>
1N/A
1N/A $Test->cmp_ok($this, $type, $that, $name);
1N/A
1N/AWorks just like Test::More's cmp_ok().
1N/A
1N/A $Test->cmp_ok($big_num, '!=', $other_big_num);
1N/A
1N/A=cut
1N/A
1N/Asub cmp_ok {
1N/A my($self, $got, $type, $expect, $name) = @_;
1N/A
1N/A my $test;
1N/A {
1N/A local $^W = 0;
1N/A local($@,$!); # don't interfere with $@
1N/A # eval() sometimes resets $!
1N/A $test = eval "\$got $type \$expect";
1N/A }
1N/A local $Level = $Level + 1;
1N/A my $ok = $self->ok($test, $name);
1N/A
1N/A unless( $ok ) {
1N/A if( $type =~ /^(eq|==)$/ ) {
1N/A $self->_is_diag($got, $type, $expect);
1N/A }
1N/A else {
1N/A $self->_cmp_diag($got, $type, $expect);
1N/A }
1N/A }
1N/A return $ok;
1N/A}
1N/A
1N/Asub _cmp_diag {
1N/A my($self, $got, $type, $expect) = @_;
1N/A
1N/A $got = defined $got ? "'$got'" : 'undef';
1N/A $expect = defined $expect ? "'$expect'" : 'undef';
1N/A return $self->diag(sprintf <<DIAGNOSTIC, $got, $type, $expect);
1N/A %s
1N/A %s
1N/A %s
1N/ADIAGNOSTIC
1N/A}
1N/A
1N/A=item B<BAILOUT>
1N/A
1N/A $Test->BAILOUT($reason);
1N/A
1N/AIndicates to the Test::Harness that things are going so badly all
1N/Atesting should terminate. This includes running any additional test
1N/Ascripts.
1N/A
1N/AIt will exit with 255.
1N/A
1N/A=cut
1N/A
1N/Asub BAILOUT {
1N/A my($self, $reason) = @_;
1N/A
1N/A $self->_print("Bail out! $reason");
1N/A exit 255;
1N/A}
1N/A
1N/A=item B<skip>
1N/A
1N/A $Test->skip;
1N/A $Test->skip($why);
1N/A
1N/ASkips the current test, reporting $why.
1N/A
1N/A=cut
1N/A
1N/Asub skip {
1N/A my($self, $why) = @_;
1N/A $why ||= '';
1N/A
1N/A unless( $Have_Plan ) {
1N/A require Carp;
1N/A Carp::croak("You tried to run tests without a plan! Gotta have a plan.");
1N/A }
1N/A
1N/A lock($Curr_Test);
1N/A $Curr_Test++;
1N/A
1N/A my %result;
1N/A share(%result);
1N/A %result = (
1N/A 'ok' => 1,
1N/A actual_ok => 1,
1N/A name => '',
1N/A type => 'skip',
1N/A reason => $why,
1N/A );
1N/A $Test_Results[$Curr_Test-1] = \%result;
1N/A
1N/A my $out = "ok";
1N/A $out .= " $Curr_Test" if $self->use_numbers;
1N/A $out .= " # skip $why\n";
1N/A
1N/A $Test->_print($out);
1N/A
1N/A return 1;
1N/A}
1N/A
1N/A
1N/A=item B<todo_skip>
1N/A
1N/A $Test->todo_skip;
1N/A $Test->todo_skip($why);
1N/A
1N/ALike skip(), only it will declare the test as failing and TODO. Similar
1N/Ato
1N/A
1N/A print "not ok $tnum # TODO $why\n";
1N/A
1N/A=cut
1N/A
1N/Asub todo_skip {
1N/A my($self, $why) = @_;
1N/A $why ||= '';
1N/A
1N/A unless( $Have_Plan ) {
1N/A require Carp;
1N/A Carp::croak("You tried to run tests without a plan! Gotta have a plan.");
1N/A }
1N/A
1N/A lock($Curr_Test);
1N/A $Curr_Test++;
1N/A
1N/A my %result;
1N/A share(%result);
1N/A %result = (
1N/A 'ok' => 1,
1N/A actual_ok => 0,
1N/A name => '',
1N/A type => 'todo_skip',
1N/A reason => $why,
1N/A );
1N/A
1N/A $Test_Results[$Curr_Test-1] = \%result;
1N/A
1N/A my $out = "not ok";
1N/A $out .= " $Curr_Test" if $self->use_numbers;
1N/A $out .= " # TODO & SKIP $why\n";
1N/A
1N/A $Test->_print($out);
1N/A
1N/A return 1;
1N/A}
1N/A
1N/A
1N/A=begin _unimplemented
1N/A
1N/A=item B<skip_rest>
1N/A
1N/A $Test->skip_rest;
1N/A $Test->skip_rest($reason);
1N/A
1N/ALike skip(), only it skips all the rest of the tests you plan to run
1N/Aand terminates the test.
1N/A
1N/AIf you're running under no_plan, it skips once and terminates the
1N/Atest.
1N/A
1N/A=end _unimplemented
1N/A
1N/A=back
1N/A
1N/A
1N/A=head2 Test style
1N/A
1N/A=over 4
1N/A
1N/A=item B<level>
1N/A
1N/A $Test->level($how_high);
1N/A
1N/AHow far up the call stack should $Test look when reporting where the
1N/Atest failed.
1N/A
1N/ADefaults to 1.
1N/A
1N/ASetting $Test::Builder::Level overrides. This is typically useful
1N/Alocalized:
1N/A
1N/A {
1N/A local $Test::Builder::Level = 2;
1N/A $Test->ok($test);
1N/A }
1N/A
1N/A=cut
1N/A
1N/Asub level {
1N/A my($self, $level) = @_;
1N/A
1N/A if( defined $level ) {
1N/A $Level = $level;
1N/A }
1N/A return $Level;
1N/A}
1N/A
1N/A$CLASS->level(1);
1N/A
1N/A
1N/A=item B<use_numbers>
1N/A
1N/A $Test->use_numbers($on_or_off);
1N/A
1N/AWhether or not the test should output numbers. That is, this if true:
1N/A
1N/A ok 1
1N/A ok 2
1N/A ok 3
1N/A
1N/Aor this if false
1N/A
1N/A ok
1N/A ok
1N/A ok
1N/A
1N/AMost useful when you can't depend on the test output order, such as
1N/Awhen threads or forking is involved.
1N/A
1N/ATest::Harness will accept either, but avoid mixing the two styles.
1N/A
1N/ADefaults to on.
1N/A
1N/A=cut
1N/A
1N/Amy $Use_Nums = 1;
1N/Asub use_numbers {
1N/A my($self, $use_nums) = @_;
1N/A
1N/A if( defined $use_nums ) {
1N/A $Use_Nums = $use_nums;
1N/A }
1N/A return $Use_Nums;
1N/A}
1N/A
1N/A=item B<no_header>
1N/A
1N/A $Test->no_header($no_header);
1N/A
1N/AIf set to true, no "1..N" header will be printed.
1N/A
1N/A=item B<no_ending>
1N/A
1N/A $Test->no_ending($no_ending);
1N/A
1N/ANormally, Test::Builder does some extra diagnostics when the test
1N/Aends. It also changes the exit code as described in Test::Simple.
1N/A
1N/AIf this is true, none of that will be done.
1N/A
1N/A=cut
1N/A
1N/Amy($No_Header, $No_Ending) = (0,0);
1N/Asub no_header {
1N/A my($self, $no_header) = @_;
1N/A
1N/A if( defined $no_header ) {
1N/A $No_Header = $no_header;
1N/A }
1N/A return $No_Header;
1N/A}
1N/A
1N/Asub no_ending {
1N/A my($self, $no_ending) = @_;
1N/A
1N/A if( defined $no_ending ) {
1N/A $No_Ending = $no_ending;
1N/A }
1N/A return $No_Ending;
1N/A}
1N/A
1N/A
1N/A=back
1N/A
1N/A=head2 Output
1N/A
1N/AControlling where the test output goes.
1N/A
1N/AIt's ok for your test to change where STDOUT and STDERR point to,
1N/ATest::Builder's default output settings will not be affected.
1N/A
1N/A=over 4
1N/A
1N/A=item B<diag>
1N/A
1N/A $Test->diag(@msgs);
1N/A
1N/APrints out the given $message. Normally, it uses the failure_output()
1N/Ahandle, but if this is for a TODO test, the todo_output() handle is
1N/Aused.
1N/A
1N/AOutput will be indented and marked with a # so as not to interfere
1N/Awith test output. A newline will be put on the end if there isn't one
1N/Aalready.
1N/A
1N/AWe encourage using this rather than calling print directly.
1N/A
1N/AReturns false. Why? Because diag() is often used in conjunction with
1N/Aa failing test (C<ok() || diag()>) it "passes through" the failure.
1N/A
1N/A return ok(...) || diag(...);
1N/A
1N/A=for blame transfer
1N/AMark Fowler <mark@twoshortplanks.com>
1N/A
1N/A=cut
1N/A
1N/Asub diag {
1N/A my($self, @msgs) = @_;
1N/A return unless @msgs;
1N/A
1N/A # Prevent printing headers when compiling (i.e. -c)
1N/A return if $^C;
1N/A
1N/A # Escape each line with a #.
1N/A foreach (@msgs) {
1N/A $_ = 'undef' unless defined;
1N/A s/^/# /gms;
1N/A }
1N/A
1N/A push @msgs, "\n" unless $msgs[-1] =~ /\n\Z/;
1N/A
1N/A local $Level = $Level + 1;
1N/A my $fh = $self->todo ? $self->todo_output : $self->failure_output;
1N/A local($\, $", $,) = (undef, ' ', '');
1N/A print $fh @msgs;
1N/A
1N/A return 0;
1N/A}
1N/A
1N/A=begin _private
1N/A
1N/A=item B<_print>
1N/A
1N/A $Test->_print(@msgs);
1N/A
1N/APrints to the output() filehandle.
1N/A
1N/A=end _private
1N/A
1N/A=cut
1N/A
1N/Asub _print {
1N/A my($self, @msgs) = @_;
1N/A
1N/A # Prevent printing headers when only compiling. Mostly for when
1N/A # tests are deparsed with B::Deparse
1N/A return if $^C;
1N/A
1N/A local($\, $", $,) = (undef, ' ', '');
1N/A my $fh = $self->output;
1N/A
1N/A # Escape each line after the first with a # so we don't
1N/A # confuse Test::Harness.
1N/A foreach (@msgs) {
1N/A s/\n(.)/\n# $1/sg;
1N/A }
1N/A
1N/A push @msgs, "\n" unless $msgs[-1] =~ /\n\Z/;
1N/A
1N/A print $fh @msgs;
1N/A}
1N/A
1N/A
1N/A=item B<output>
1N/A
1N/A $Test->output($fh);
1N/A $Test->output($file);
1N/A
1N/AWhere normal "ok/not ok" test output should go.
1N/A
1N/ADefaults to STDOUT.
1N/A
1N/A=item B<failure_output>
1N/A
1N/A $Test->failure_output($fh);
1N/A $Test->failure_output($file);
1N/A
1N/AWhere diagnostic output on test failures and diag() should go.
1N/A
1N/ADefaults to STDERR.
1N/A
1N/A=item B<todo_output>
1N/A
1N/A $Test->todo_output($fh);
1N/A $Test->todo_output($file);
1N/A
1N/AWhere diagnostics about todo test failures and diag() should go.
1N/A
1N/ADefaults to STDOUT.
1N/A
1N/A=cut
1N/A
1N/Amy($Out_FH, $Fail_FH, $Todo_FH);
1N/Asub output {
1N/A my($self, $fh) = @_;
1N/A
1N/A if( defined $fh ) {
1N/A $Out_FH = _new_fh($fh);
1N/A }
1N/A return $Out_FH;
1N/A}
1N/A
1N/Asub failure_output {
1N/A my($self, $fh) = @_;
1N/A
1N/A if( defined $fh ) {
1N/A $Fail_FH = _new_fh($fh);
1N/A }
1N/A return $Fail_FH;
1N/A}
1N/A
1N/Asub todo_output {
1N/A my($self, $fh) = @_;
1N/A
1N/A if( defined $fh ) {
1N/A $Todo_FH = _new_fh($fh);
1N/A }
1N/A return $Todo_FH;
1N/A}
1N/A
1N/Asub _new_fh {
1N/A my($file_or_fh) = shift;
1N/A
1N/A my $fh;
1N/A unless( UNIVERSAL::isa($file_or_fh, 'GLOB') ) {
1N/A $fh = do { local *FH };
1N/A open $fh, ">$file_or_fh" or
1N/A die "Can't open test output log $file_or_fh: $!";
1N/A }
1N/A else {
1N/A $fh = $file_or_fh;
1N/A }
1N/A
1N/A return $fh;
1N/A}
1N/A
1N/Aunless( $^C ) {
1N/A # We dup STDOUT and STDERR so people can change them in their
1N/A # test suites while still getting normal test output.
1N/A open(TESTOUT, ">&STDOUT") or die "Can't dup STDOUT: $!";
1N/A open(TESTERR, ">&STDERR") or die "Can't dup STDERR: $!";
1N/A
1N/A # Set everything to unbuffered else plain prints to STDOUT will
1N/A # come out in the wrong order from our own prints.
1N/A _autoflush(\*TESTOUT);
1N/A _autoflush(\*STDOUT);
1N/A _autoflush(\*TESTERR);
1N/A _autoflush(\*STDERR);
1N/A
1N/A $CLASS->output(\*TESTOUT);
1N/A $CLASS->failure_output(\*TESTERR);
1N/A $CLASS->todo_output(\*TESTOUT);
1N/A}
1N/A
1N/Asub _autoflush {
1N/A my($fh) = shift;
1N/A my $old_fh = select $fh;
1N/A $| = 1;
1N/A select $old_fh;
1N/A}
1N/A
1N/A
1N/A=back
1N/A
1N/A
1N/A=head2 Test Status and Info
1N/A
1N/A=over 4
1N/A
1N/A=item B<current_test>
1N/A
1N/A my $curr_test = $Test->current_test;
1N/A $Test->current_test($num);
1N/A
1N/AGets/sets the current test # we're on.
1N/A
1N/AYou usually shouldn't have to set this.
1N/A
1N/A=cut
1N/A
1N/Asub current_test {
1N/A my($self, $num) = @_;
1N/A
1N/A lock($Curr_Test);
1N/A if( defined $num ) {
1N/A unless( $Have_Plan ) {
1N/A require Carp;
1N/A Carp::croak("Can't change the current test number without a plan!");
1N/A }
1N/A
1N/A $Curr_Test = $num;
1N/A if( $num > @Test_Results ) {
1N/A my $start = @Test_Results ? $#Test_Results + 1 : 0;
1N/A for ($start..$num-1) {
1N/A my %result;
1N/A share(%result);
1N/A %result = ( ok => 1,
1N/A actual_ok => undef,
1N/A reason => 'incrementing test number',
1N/A type => 'unknown',
1N/A name => undef
1N/A );
1N/A $Test_Results[$_] = \%result;
1N/A }
1N/A }
1N/A }
1N/A return $Curr_Test;
1N/A}
1N/A
1N/A
1N/A=item B<summary>
1N/A
1N/A my @tests = $Test->summary;
1N/A
1N/AA simple summary of the tests so far. True for pass, false for fail.
1N/AThis is a logical pass/fail, so todos are passes.
1N/A
1N/AOf course, test #1 is $tests[0], etc...
1N/A
1N/A=cut
1N/A
1N/Asub summary {
1N/A my($self) = shift;
1N/A
1N/A return map { $_->{'ok'} } @Test_Results;
1N/A}
1N/A
1N/A=item B<details>
1N/A
1N/A my @tests = $Test->details;
1N/A
1N/ALike summary(), but with a lot more detail.
1N/A
1N/A $tests[$test_num - 1] =
1N/A { 'ok' => is the test considered a pass?
1N/A actual_ok => did it literally say 'ok'?
1N/A name => name of the test (if any)
1N/A type => type of test (if any, see below).
1N/A reason => reason for the above (if any)
1N/A };
1N/A
1N/A'ok' is true if Test::Harness will consider the test to be a pass.
1N/A
1N/A'actual_ok' is a reflection of whether or not the test literally
1N/Aprinted 'ok' or 'not ok'. This is for examining the result of 'todo'
1N/Atests.
1N/A
1N/A'name' is the name of the test.
1N/A
1N/A'type' indicates if it was a special test. Normal tests have a type
1N/Aof ''. Type can be one of the following:
1N/A
1N/A skip see skip()
1N/A todo see todo()
1N/A todo_skip see todo_skip()
1N/A unknown see below
1N/A
1N/ASometimes the Test::Builder test counter is incremented without it
1N/Aprinting any test output, for example, when current_test() is changed.
1N/AIn these cases, Test::Builder doesn't know the result of the test, so
1N/Ait's type is 'unkown'. These details for these tests are filled in.
1N/AThey are considered ok, but the name and actual_ok is left undef.
1N/A
1N/AFor example "not ok 23 - hole count # TODO insufficient donuts" would
1N/Aresult in this structure:
1N/A
1N/A $tests[22] = # 23 - 1, since arrays start from 0.
1N/A { ok => 1, # logically, the test passed since it's todo
1N/A actual_ok => 0, # in absolute terms, it failed
1N/A name => 'hole count',
1N/A type => 'todo',
1N/A reason => 'insufficient donuts'
1N/A };
1N/A
1N/A=cut
1N/A
1N/Asub details {
1N/A return @Test_Results;
1N/A}
1N/A
1N/A=item B<todo>
1N/A
1N/A my $todo_reason = $Test->todo;
1N/A my $todo_reason = $Test->todo($pack);
1N/A
1N/Atodo() looks for a $TODO variable in your tests. If set, all tests
1N/Awill be considered 'todo' (see Test::More and Test::Harness for
1N/Adetails). Returns the reason (ie. the value of $TODO) if running as
1N/Atodo tests, false otherwise.
1N/A
1N/Atodo() is pretty part about finding the right package to look for
1N/A$TODO in. It uses the exported_to() package to find it. If that's
1N/Anot set, it's pretty good at guessing the right package to look at.
1N/A
1N/ASometimes there is some confusion about where todo() should be looking
1N/Afor the $TODO variable. If you want to be sure, tell it explicitly
1N/Awhat $pack to use.
1N/A
1N/A=cut
1N/A
1N/Asub todo {
1N/A my($self, $pack) = @_;
1N/A
1N/A $pack = $pack || $self->exported_to || $self->caller(1);
1N/A
1N/A no strict 'refs';
1N/A return defined ${$pack.'::TODO'} ? ${$pack.'::TODO'}
1N/A : 0;
1N/A}
1N/A
1N/A=item B<caller>
1N/A
1N/A my $package = $Test->caller;
1N/A my($pack, $file, $line) = $Test->caller;
1N/A my($pack, $file, $line) = $Test->caller($height);
1N/A
1N/ALike the normal caller(), except it reports according to your level().
1N/A
1N/A=cut
1N/A
1N/Asub caller {
1N/A my($self, $height) = @_;
1N/A $height ||= 0;
1N/A
1N/A my @caller = CORE::caller($self->level + $height + 1);
1N/A return wantarray ? @caller : $caller[0];
1N/A}
1N/A
1N/A=back
1N/A
1N/A=cut
1N/A
1N/A=begin _private
1N/A
1N/A=over 4
1N/A
1N/A=item B<_sanity_check>
1N/A
1N/A _sanity_check();
1N/A
1N/ARuns a bunch of end of test sanity checks to make sure reality came
1N/Athrough ok. If anything is wrong it will die with a fairly friendly
1N/Aerror message.
1N/A
1N/A=cut
1N/A
1N/A#'#
1N/Asub _sanity_check {
1N/A _whoa($Curr_Test < 0, 'Says here you ran a negative number of tests!');
1N/A _whoa(!$Have_Plan and $Curr_Test,
1N/A 'Somehow your tests ran without a plan!');
1N/A _whoa($Curr_Test != @Test_Results,
1N/A 'Somehow you got a different number of results than tests ran!');
1N/A}
1N/A
1N/A=item B<_whoa>
1N/A
1N/A _whoa($check, $description);
1N/A
1N/AA sanity check, similar to assert(). If the $check is true, something
1N/Ahas gone horribly wrong. It will die with the given $description and
1N/Aa note to contact the author.
1N/A
1N/A=cut
1N/A
1N/Asub _whoa {
1N/A my($check, $desc) = @_;
1N/A if( $check ) {
1N/A die <<WHOA;
1N/AWHOA! $desc
1N/AThis should never happen! Please contact the author immediately!
1N/AWHOA
1N/A }
1N/A}
1N/A
1N/A=item B<_my_exit>
1N/A
1N/A _my_exit($exit_num);
1N/A
1N/APerl seems to have some trouble with exiting inside an END block. 5.005_03
1N/Aand 5.6.1 both seem to do odd things. Instead, this function edits $?
1N/Adirectly. It should ONLY be called from inside an END block. It
1N/Adoesn't actually exit, that's your job.
1N/A
1N/A=cut
1N/A
1N/Asub _my_exit {
1N/A $? = $_[0];
1N/A
1N/A return 1;
1N/A}
1N/A
1N/A
1N/A=back
1N/A
1N/A=end _private
1N/A
1N/A=cut
1N/A
1N/A$SIG{__DIE__} = sub {
1N/A # We don't want to muck with death in an eval, but $^S isn't
1N/A # totally reliable. 5.005_03 and 5.6.1 both do the wrong thing
1N/A # with it. Instead, we use caller. This also means it runs under
1N/A # 5.004!
1N/A my $in_eval = 0;
1N/A for( my $stack = 1; my $sub = (CORE::caller($stack))[3]; $stack++ ) {
1N/A $in_eval = 1 if $sub =~ /^\(eval\)/;
1N/A }
1N/A $Test_Died = 1 unless $in_eval;
1N/A};
1N/A
1N/Asub _ending {
1N/A my $self = shift;
1N/A
1N/A _sanity_check();
1N/A
1N/A # Don't bother with an ending if this is a forked copy. Only the parent
1N/A # should do the ending.
1N/A do{ _my_exit($?) && return } if $Original_Pid != $$;
1N/A
1N/A # Bailout if plan() was never called. This is so
1N/A # "require Test::Simple" doesn't puke.
1N/A do{ _my_exit(0) && return } if !$Have_Plan && !$Test_Died;
1N/A
1N/A # Figure out if we passed or failed and print helpful messages.
1N/A if( @Test_Results ) {
1N/A # The plan? We have no plan.
1N/A if( $No_Plan ) {
1N/A $self->_print("1..$Curr_Test\n") unless $self->no_header;
1N/A $Expected_Tests = $Curr_Test;
1N/A }
1N/A
1N/A # 5.8.0 threads bug. Shared arrays will not be auto-extended
1N/A # by a slice. Worse, we have to fill in every entry else
1N/A # we'll get an "Invalid value for shared scalar" error
1N/A for my $idx ($#Test_Results..$Expected_Tests-1) {
1N/A my %empty_result = ();
1N/A share(%empty_result);
1N/A $Test_Results[$idx] = \%empty_result
1N/A unless defined $Test_Results[$idx];
1N/A }
1N/A
1N/A my $num_failed = grep !$_->{'ok'}, @Test_Results[0..$Expected_Tests-1];
1N/A $num_failed += abs($Expected_Tests - @Test_Results);
1N/A
1N/A if( $Curr_Test < $Expected_Tests ) {
1N/A $self->diag(<<"FAIL");
1N/ALooks like you planned $Expected_Tests tests but only ran $Curr_Test.
1N/AFAIL
1N/A }
1N/A elsif( $Curr_Test > $Expected_Tests ) {
1N/A my $num_extra = $Curr_Test - $Expected_Tests;
1N/A $self->diag(<<"FAIL");
1N/ALooks like you planned $Expected_Tests tests but ran $num_extra extra.
1N/AFAIL
1N/A }
1N/A elsif ( $num_failed ) {
1N/A $self->diag(<<"FAIL");
1N/ALooks like you failed $num_failed tests of $Expected_Tests.
1N/AFAIL
1N/A }
1N/A
1N/A if( $Test_Died ) {
1N/A $self->diag(<<"FAIL");
1N/ALooks like your test died just after $Curr_Test.
1N/AFAIL
1N/A
1N/A _my_exit( 255 ) && return;
1N/A }
1N/A
1N/A _my_exit( $num_failed <= 254 ? $num_failed : 254 ) && return;
1N/A }
1N/A elsif ( $Skip_All ) {
1N/A _my_exit( 0 ) && return;
1N/A }
1N/A elsif ( $Test_Died ) {
1N/A $self->diag(<<'FAIL');
1N/ALooks like your test died before it could output anything.
1N/AFAIL
1N/A }
1N/A else {
1N/A $self->diag("No tests run!\n");
1N/A _my_exit( 255 ) && return;
1N/A }
1N/A}
1N/A
1N/AEND {
1N/A $Test->_ending if defined $Test and !$Test->no_ending;
1N/A}
1N/A
1N/A=head1 THREADS
1N/A
1N/AIn perl 5.8.0 and later, Test::Builder is thread-safe. The test
1N/Anumber is shared amongst all threads. This means if one thread sets
1N/Athe test number using current_test() they will all be effected.
1N/A
1N/A=head1 EXAMPLES
1N/A
1N/ACPAN can provide the best examples. Test::Simple, Test::More,
1N/ATest::Exception and Test::Differences all use Test::Builder.
1N/A
1N/A=head1 SEE ALSO
1N/A
1N/ATest::Simple, Test::More, Test::Harness
1N/A
1N/A=head1 AUTHORS
1N/A
1N/AOriginal code by chromatic, maintained by Michael G Schwern
1N/AE<lt>schwern@pobox.comE<gt>
1N/A
1N/A=head1 COPYRIGHT
1N/A
1N/ACopyright 2002 by chromatic E<lt>chromatic@wgz.orgE<gt>,
1N/A Michael G Schwern E<lt>schwern@pobox.comE<gt>.
1N/A
1N/AThis program is free software; you can redistribute it and/or
1N/Amodify it under the same terms as Perl itself.
1N/A
1N/ASee F<http://www.perl.com/perl/misc/Artistic.html>
1N/A
1N/A=cut
1N/A
1N/A1;