Minor naming change UTF8_IS_ASCII => UTF8_IS_INVARIANT
[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";
e5420382 89 # Replace with one of a pair of single print()'s as a workaround:
90 if (!$ok) {
91 print $TESTOUT "not ok $ntest\n";
92 }
93 else {
94 print $TESTOUT "ok $ntest\n";
95 }
8b3be1d1 96
97 if (!$ok) {
98 my $detail = { 'repetition' => $repetition, 'package' => $pkg,
f2ac83ee 99 'result' => $result, 'todo' => $todo };
8b3be1d1 100 $$detail{expected} = $expected if defined $expected;
101 $diag = $$detail{diagnostic} = to_value(shift) if @_;
f2ac83ee 102 $context .= ' *TODO*' if $todo;
8b3be1d1 103 if (!defined $expected) {
3238f5fe 104 if (!$diag) {
f2ac83ee 105 print $TESTOUT "# Failed test $ntest in $context\n";
3238f5fe 106 } else {
f2ac83ee 107 print $TESTOUT "# Failed test $ntest in $context: $diag\n";
3238f5fe 108 }
8b3be1d1 109 } else {
110 my $prefix = "Test $ntest";
59e80644 111 print $TESTOUT "# $prefix got: ".
112 (defined $result? "'$result'":'<UNDEF>')." ($context)\n";
8b3be1d1 113 $prefix = ' ' x (length($prefix) - 5);
f63ceb1c 114 if ((ref($expected)||'') eq 'Regexp') {
f2ac83ee 115 $expected = 'qr/'.$expected.'/'
116 } else {
117 $expected = "'$expected'";
118 }
8b3be1d1 119 if (!$diag) {
f2ac83ee 120 print $TESTOUT "# $prefix Expected: $expected\n";
3238f5fe 121 } else {
f2ac83ee 122 print $TESTOUT "# $prefix Expected: $expected ($diag)\n";
3238f5fe 123 }
124 }
8b3be1d1 125 push @FAILDETAIL, $detail;
7b13a3f5 126 }
7b13a3f5 127 }
128 ++ $ntest;
129 $ok;
130}
131
8b3be1d1 132sub skip ($$;$$) {
f2ac83ee 133 my $whyskip = to_value(shift);
134 if ($whyskip) {
135 $whyskip = 'skip' if $whyskip =~ m/^\d+$/;
136 print $TESTOUT "ok $ntest # $whyskip\n";
7b13a3f5 137 ++ $ntest;
138 1;
139 } else {
8b3be1d1 140 local($TestLevel) = $TestLevel+1; #ignore this stack frame
141 &ok;
7b13a3f5 142 }
143}
144
8b3be1d1 145END {
146 $ONFAIL->(\@FAILDETAIL) if @FAILDETAIL && $ONFAIL;
147}
148
7b13a3f5 1491;
150__END__
151
152=head1 NAME
153
bbc7dcd2 154Test - provides a simple framework for writing test scripts
7b13a3f5 155
156=head1 SYNOPSIS
157
158 use strict;
159 use Test;
f2ac83ee 160
161 # use a BEGIN block so we print our plan before MyModule is loaded
162 BEGIN { plan tests => 14, todo => [3,4] }
163
164 # load your module...
165 use MyModule;
3238f5fe 166
167 ok(0); # failure
168 ok(1); # success
169
170 ok(0); # ok, expected failure (see todo list, above)
171 ok(1); # surprise success!
172
173 ok(0,1); # failure: '0' ne '1'
174 ok('broke','fixed'); # failure: 'broke' ne 'fixed'
175 ok('fixed','fixed'); # success: 'fixed' eq 'fixed'
f2ac83ee 176 ok('fixed',qr/x/); # success: 'fixed' =~ qr/x/
7b13a3f5 177
3238f5fe 178 ok(sub { 1+1 }, 2); # success: '2' eq '2'
179 ok(sub { 1+1 }, 3); # failure: '2' ne '3'
59e80644 180 ok(0, int(rand(2)); # (just kidding :-)
7b13a3f5 181
3238f5fe 182 my @list = (0,0);
8b3be1d1 183 ok @list, 3, "\@list=".join(',',@list); #extra diagnostics
184 ok 'segmentation fault', '/(?i)success/'; #regex match
7b13a3f5 185
3238f5fe 186 skip($feature_is_missing, ...); #do platform specific test
7b13a3f5 187
188=head1 DESCRIPTION
189
d032053e 190L<Test::Harness|Test::Harness> expects to see particular output when it
191executes tests. This module aims to make writing proper test scripts just
192a little bit easier (and less error prone :-).
7b13a3f5 193
3238f5fe 194=head1 TEST TYPES
7b13a3f5 195
196=over 4
197
198=item * NORMAL TESTS
199
f2ac83ee 200These tests are expected to succeed. If they don't something's
3238f5fe 201screwed up!
7b13a3f5 202
203=item * SKIPPED TESTS
204
f2ac83ee 205Skip is for tests that might or might not be possible to run depending
206on the availability of platform specific features. The first argument
207should evaluate to true (think "yes, please skip") if the required
208feature is not available. After the first argument, skip works
3238f5fe 209exactly the same way as do normal tests.
7b13a3f5 210
211=item * TODO TESTS
212
f2ac83ee 213TODO tests are designed for maintaining an B<executable TODO list>.
214These tests are expected NOT to succeed. If a TODO test does succeed,
215the feature in question should not be on the TODO list, now should it?
7b13a3f5 216
f2ac83ee 217Packages should NOT be released with succeeding TODO tests. As soon
7b13a3f5 218as a TODO test starts working, it should be promoted to a normal test
f2ac83ee 219and the newly working feature should be documented in the release
220notes or change log.
7b13a3f5 221
222=back
223
f2ac83ee 224=head1 RETURN VALUE
225
226Both C<ok> and C<skip> return true if their test succeeds and false
227otherwise in a scalar context.
228
8b3be1d1 229=head1 ONFAIL
230
231 BEGIN { plan test => 4, onfail => sub { warn "CALL 911!" } }
232
f2ac83ee 233While test failures should be enough, extra diagnostics can be
234triggered at the end of a test run. C<onfail> is passed an array ref
235of hash refs that describe each test failure. Each hash will contain
236at least the following fields: C<package>, C<repetition>, and
237C<result>. (The file, line, and test number are not included because
f610777f 238their correspondence to a particular test is tenuous.) If the test
f2ac83ee 239had an expected value or a diagnostic string, these will also be
240included.
241
242The B<optional> C<onfail> hook might be used simply to print out the
243version of your package and/or how to report problems. It might also
244be used to generate extremely sophisticated diagnostics for a
245particularly bizarre test failure. However it's not a panacea. Core
246dumps or other unrecoverable errors prevent the C<onfail> hook from
247running. (It is run inside an C<END> block.) Besides, C<onfail> is
248probably over-kill in most cases. (Your test code should be simpler
8b3be1d1 249than the code it is testing, yes?)
250
7b13a3f5 251=head1 SEE ALSO
252
f2ac83ee 253L<Test::Harness> and, perhaps, test coverage analysis tools.
7b13a3f5 254
255=head1 AUTHOR
256
59e80644 257Copyright (c) 1998-1999 Joshua Nathaniel Pritikin. All rights reserved.
7b13a3f5 258
259This package is free software and is provided "as is" without express
260or implied warranty. It may be used, redistributed and/or modified
261under the terms of the Perl Artistic License (see
262http://www.perl.com/perl/misc/Artistic.html)
263
264=cut