Integrate perlio:
[p5sagit/p5-mst-13.2.git] / lib / Test.pm
CommitLineData
7b13a3f5 1use strict;
2package Test;
3use Test::Harness 1.1601 ();
4use Carp;
17f410f9 5our($VERSION, @ISA, @EXPORT, @EXPORT_OK, $ntest, $TestLevel); #public-ish
6our($TESTOUT, $ONFAIL, %todo, %history, $planned, @FAILDETAIL); #private-ish
2a88172d 7$VERSION = '1.15';
7b13a3f5 8require Exporter;
9@ISA=('Exporter');
f2ac83ee 10@EXPORT=qw(&plan &ok &skip);
11@EXPORT_OK=qw($ntest $TESTOUT);
7b13a3f5 12
3238f5fe 13$TestLevel = 0; # how many extra stack frames to skip
7b13a3f5 14$|=1;
15#$^W=1; ?
16$ntest=1;
f2ac83ee 17$TESTOUT = *STDOUT{IO};
7b13a3f5 18
3238f5fe 19# Use of this variable is strongly discouraged. It is set mainly to
20# help test coverage analyzers know which test is running.
7b13a3f5 21$ENV{REGRESSION_TEST} = $0;
22
23sub plan {
24 croak "Test::plan(%args): odd number of arguments" if @_ & 1;
8b3be1d1 25 croak "Test::plan(): should not be called more than once" if $planned;
7b13a3f5 26 my $max=0;
27 for (my $x=0; $x < @_; $x+=2) {
28 my ($k,$v) = @_[$x,$x+1];
29 if ($k =~ /^test(s)?$/) { $max = $v; }
30 elsif ($k eq 'todo' or
31 $k eq 'failok') { for (@$v) { $todo{$_}=1; }; }
8b3be1d1 32 elsif ($k eq 'onfail') {
33 ref $v eq 'CODE' or croak "Test::plan(onfail => $v): must be CODE";
34 $ONFAIL = $v;
35 }
7b13a3f5 36 else { carp "Test::plan(): skipping unrecognized directive '$k'" }
37 }
38 my @todo = sort { $a <=> $b } keys %todo;
39 if (@todo) {
f2ac83ee 40 print $TESTOUT "1..$max todo ".join(' ', @todo).";\n";
7b13a3f5 41 } else {
f2ac83ee 42 print $TESTOUT "1..$max\n";
7b13a3f5 43 }
8b3be1d1 44 ++$planned;
7b13a3f5 45}
46
3238f5fe 47sub to_value {
48 my ($v) = @_;
49 (ref $v or '') eq 'CODE' ? $v->() : $v;
50}
51
8b3be1d1 52sub ok ($;$$) {
53 croak "ok: plan before you test!" if !$planned;
3238f5fe 54 my ($pkg,$file,$line) = caller($TestLevel);
55 my $repetition = ++$history{"$file:$line"};
56 my $context = ("$file at line $line".
8b3be1d1 57 ($repetition > 1 ? " fail \#$repetition" : ''));
3238f5fe 58 my $ok=0;
8b3be1d1 59 my $result = to_value(shift);
60 my ($expected,$diag);
3238f5fe 61 if (@_ == 0) {
8b3be1d1 62 $ok = $result;
3238f5fe 63 } else {
8b3be1d1 64 $expected = to_value(shift);
8b3be1d1 65 my ($regex,$ignore);
59e80644 66 if (!defined $expected) {
67 $ok = !defined $result;
68 } elsif (!defined $result) {
69 $ok = 0;
70 } elsif ((ref($expected)||'') eq 'Regexp') {
f2ac83ee 71 $ok = $result =~ /$expected/;
72 } elsif (($regex) = ($expected =~ m,^ / (.+) / $,sx) or
8b3be1d1 73 ($ignore, $regex) = ($expected =~ m,^ m([^\w\s]) (.+) \1 $,sx)) {
74 $ok = $result =~ /$regex/;
3238f5fe 75 } else {
3238f5fe 76 $ok = $result eq $expected;
77 }
8b3be1d1 78 }
f2ac83ee 79 my $todo = $todo{$ntest};
80 if ($todo and $ok) {
81 $context .= ' TODO?!' if $todo;
82 print $TESTOUT "ok $ntest # ($context)\n";
8b3be1d1 83 } else {
2a88172d 84 # Issuing two separate print()s causes severe trouble with
85 # Test::Harness on VMS. The "not "'s for failed tests occur
86 # on a separate line and would not get counted as failures.
87 #print $TESTOUT "not " if !$ok;
88 #print $TESTOUT "ok $ntest\n";
89 # Replace with a single print() as a workaround:
90 my $okline = '';
91 $okline = "not " if !$ok;
92 $okline .= "ok $ntest\n";
93 print $TESTOUT $okline;
8b3be1d1 94
95 if (!$ok) {
96 my $detail = { 'repetition' => $repetition, 'package' => $pkg,
f2ac83ee 97 'result' => $result, 'todo' => $todo };
8b3be1d1 98 $$detail{expected} = $expected if defined $expected;
99 $diag = $$detail{diagnostic} = to_value(shift) if @_;
f2ac83ee 100 $context .= ' *TODO*' if $todo;
8b3be1d1 101 if (!defined $expected) {
3238f5fe 102 if (!$diag) {
f2ac83ee 103 print $TESTOUT "# Failed test $ntest in $context\n";
3238f5fe 104 } else {
f2ac83ee 105 print $TESTOUT "# Failed test $ntest in $context: $diag\n";
3238f5fe 106 }
8b3be1d1 107 } else {
108 my $prefix = "Test $ntest";
59e80644 109 print $TESTOUT "# $prefix got: ".
110 (defined $result? "'$result'":'<UNDEF>')." ($context)\n";
8b3be1d1 111 $prefix = ' ' x (length($prefix) - 5);
f63ceb1c 112 if ((ref($expected)||'') eq 'Regexp') {
f2ac83ee 113 $expected = 'qr/'.$expected.'/'
114 } else {
115 $expected = "'$expected'";
116 }
8b3be1d1 117 if (!$diag) {
f2ac83ee 118 print $TESTOUT "# $prefix Expected: $expected\n";
3238f5fe 119 } else {
f2ac83ee 120 print $TESTOUT "# $prefix Expected: $expected ($diag)\n";
3238f5fe 121 }
122 }
8b3be1d1 123 push @FAILDETAIL, $detail;
7b13a3f5 124 }
7b13a3f5 125 }
126 ++ $ntest;
127 $ok;
128}
129
8b3be1d1 130sub skip ($$;$$) {
f2ac83ee 131 my $whyskip = to_value(shift);
132 if ($whyskip) {
133 $whyskip = 'skip' if $whyskip =~ m/^\d+$/;
134 print $TESTOUT "ok $ntest # $whyskip\n";
7b13a3f5 135 ++ $ntest;
136 1;
137 } else {
8b3be1d1 138 local($TestLevel) = $TestLevel+1; #ignore this stack frame
139 &ok;
7b13a3f5 140 }
141}
142
8b3be1d1 143END {
144 $ONFAIL->(\@FAILDETAIL) if @FAILDETAIL && $ONFAIL;
145}
146
7b13a3f5 1471;
148__END__
149
150=head1 NAME
151
152 Test - provides a simple framework for writing test scripts
153
154=head1 SYNOPSIS
155
156 use strict;
157 use Test;
f2ac83ee 158
159 # use a BEGIN block so we print our plan before MyModule is loaded
160 BEGIN { plan tests => 14, todo => [3,4] }
161
162 # load your module...
163 use MyModule;
3238f5fe 164
165 ok(0); # failure
166 ok(1); # success
167
168 ok(0); # ok, expected failure (see todo list, above)
169 ok(1); # surprise success!
170
171 ok(0,1); # failure: '0' ne '1'
172 ok('broke','fixed'); # failure: 'broke' ne 'fixed'
173 ok('fixed','fixed'); # success: 'fixed' eq 'fixed'
f2ac83ee 174 ok('fixed',qr/x/); # success: 'fixed' =~ qr/x/
7b13a3f5 175
3238f5fe 176 ok(sub { 1+1 }, 2); # success: '2' eq '2'
177 ok(sub { 1+1 }, 3); # failure: '2' ne '3'
59e80644 178 ok(0, int(rand(2)); # (just kidding :-)
7b13a3f5 179
3238f5fe 180 my @list = (0,0);
8b3be1d1 181 ok @list, 3, "\@list=".join(',',@list); #extra diagnostics
182 ok 'segmentation fault', '/(?i)success/'; #regex match
7b13a3f5 183
3238f5fe 184 skip($feature_is_missing, ...); #do platform specific test
7b13a3f5 185
186=head1 DESCRIPTION
187
d032053e 188L<Test::Harness|Test::Harness> expects to see particular output when it
189executes tests. This module aims to make writing proper test scripts just
190a little bit easier (and less error prone :-).
7b13a3f5 191
3238f5fe 192=head1 TEST TYPES
7b13a3f5 193
194=over 4
195
196=item * NORMAL TESTS
197
f2ac83ee 198These tests are expected to succeed. If they don't something's
3238f5fe 199screwed up!
7b13a3f5 200
201=item * SKIPPED TESTS
202
f2ac83ee 203Skip is for tests that might or might not be possible to run depending
204on the availability of platform specific features. The first argument
205should evaluate to true (think "yes, please skip") if the required
206feature is not available. After the first argument, skip works
3238f5fe 207exactly the same way as do normal tests.
7b13a3f5 208
209=item * TODO TESTS
210
f2ac83ee 211TODO tests are designed for maintaining an B<executable TODO list>.
212These tests are expected NOT to succeed. If a TODO test does succeed,
213the feature in question should not be on the TODO list, now should it?
7b13a3f5 214
f2ac83ee 215Packages should NOT be released with succeeding TODO tests. As soon
7b13a3f5 216as a TODO test starts working, it should be promoted to a normal test
f2ac83ee 217and the newly working feature should be documented in the release
218notes or change log.
7b13a3f5 219
220=back
221
f2ac83ee 222=head1 RETURN VALUE
223
224Both C<ok> and C<skip> return true if their test succeeds and false
225otherwise in a scalar context.
226
8b3be1d1 227=head1 ONFAIL
228
229 BEGIN { plan test => 4, onfail => sub { warn "CALL 911!" } }
230
f2ac83ee 231While test failures should be enough, extra diagnostics can be
232triggered at the end of a test run. C<onfail> is passed an array ref
233of hash refs that describe each test failure. Each hash will contain
234at least the following fields: C<package>, C<repetition>, and
235C<result>. (The file, line, and test number are not included because
f610777f 236their correspondence to a particular test is tenuous.) If the test
f2ac83ee 237had an expected value or a diagnostic string, these will also be
238included.
239
240The B<optional> C<onfail> hook might be used simply to print out the
241version of your package and/or how to report problems. It might also
242be used to generate extremely sophisticated diagnostics for a
243particularly bizarre test failure. However it's not a panacea. Core
244dumps or other unrecoverable errors prevent the C<onfail> hook from
245running. (It is run inside an C<END> block.) Besides, C<onfail> is
246probably over-kill in most cases. (Your test code should be simpler
8b3be1d1 247than the code it is testing, yes?)
248
7b13a3f5 249=head1 SEE ALSO
250
f2ac83ee 251L<Test::Harness> and, perhaps, test coverage analysis tools.
7b13a3f5 252
253=head1 AUTHOR
254
59e80644 255Copyright (c) 1998-1999 Joshua Nathaniel Pritikin. All rights reserved.
7b13a3f5 256
257This package is free software and is provided "as is" without express
258or implied warranty. It may be used, redistributed and/or modified
259under the terms of the Perl Artistic License (see
260http://www.perl.com/perl/misc/Artistic.html)
261
262=cut