xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/Test.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gate
2*0Sstevel@tonic-gaterequire 5.004;
3*0Sstevel@tonic-gatepackage Test;
4*0Sstevel@tonic-gate# Time-stamp: "2003-04-18 21:48:01 AHDT"
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gateuse strict;
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gateuse Carp;
9*0Sstevel@tonic-gateuse vars (qw($VERSION @ISA @EXPORT @EXPORT_OK $ntest $TestLevel), #public-ish
10*0Sstevel@tonic-gate          qw($TESTOUT $TESTERR %Program_Lines
11*0Sstevel@tonic-gate             $ONFAIL %todo %history $planned @FAILDETAIL) #private-ish
12*0Sstevel@tonic-gate         );
13*0Sstevel@tonic-gate
14*0Sstevel@tonic-gate# In case a test is run in a persistent environment.
15*0Sstevel@tonic-gatesub _reset_globals {
16*0Sstevel@tonic-gate    %todo       = ();
17*0Sstevel@tonic-gate    %history    = ();
18*0Sstevel@tonic-gate    @FAILDETAIL = ();
19*0Sstevel@tonic-gate    $ntest      = 1;
20*0Sstevel@tonic-gate    $TestLevel  = 0;		# how many extra stack frames to skip
21*0Sstevel@tonic-gate    $planned    = 0;
22*0Sstevel@tonic-gate}
23*0Sstevel@tonic-gate
24*0Sstevel@tonic-gate$VERSION = '1.24';
25*0Sstevel@tonic-gaterequire Exporter;
26*0Sstevel@tonic-gate@ISA=('Exporter');
27*0Sstevel@tonic-gate
28*0Sstevel@tonic-gate@EXPORT    = qw(&plan &ok &skip);
29*0Sstevel@tonic-gate@EXPORT_OK = qw($ntest $TESTOUT $TESTERR);
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate$|=1;
32*0Sstevel@tonic-gate$TESTOUT = *STDOUT{IO};
33*0Sstevel@tonic-gate$TESTERR = *STDERR{IO};
34*0Sstevel@tonic-gate
35*0Sstevel@tonic-gate# Use of this variable is strongly discouraged.  It is set mainly to
36*0Sstevel@tonic-gate# help test coverage analyzers know which test is running.
37*0Sstevel@tonic-gate$ENV{REGRESSION_TEST} = $0;
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gate
40*0Sstevel@tonic-gate=head1 NAME
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gateTest - provides a simple framework for writing test scripts
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gate=head1 SYNOPSIS
45*0Sstevel@tonic-gate
46*0Sstevel@tonic-gate  use strict;
47*0Sstevel@tonic-gate  use Test;
48*0Sstevel@tonic-gate
49*0Sstevel@tonic-gate  # use a BEGIN block so we print our plan before MyModule is loaded
50*0Sstevel@tonic-gate  BEGIN { plan tests => 14, todo => [3,4] }
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate  # load your module...
53*0Sstevel@tonic-gate  use MyModule;
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gate  # Helpful notes.  All note-lines must start with a "#".
56*0Sstevel@tonic-gate  print "# I'm testing MyModule version $MyModule::VERSION\n";
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gate  ok(0); # failure
59*0Sstevel@tonic-gate  ok(1); # success
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gate  ok(0); # ok, expected failure (see todo list, above)
62*0Sstevel@tonic-gate  ok(1); # surprise success!
63*0Sstevel@tonic-gate
64*0Sstevel@tonic-gate  ok(0,1);             # failure: '0' ne '1'
65*0Sstevel@tonic-gate  ok('broke','fixed'); # failure: 'broke' ne 'fixed'
66*0Sstevel@tonic-gate  ok('fixed','fixed'); # success: 'fixed' eq 'fixed'
67*0Sstevel@tonic-gate  ok('fixed',qr/x/);   # success: 'fixed' =~ qr/x/
68*0Sstevel@tonic-gate
69*0Sstevel@tonic-gate  ok(sub { 1+1 }, 2);  # success: '2' eq '2'
70*0Sstevel@tonic-gate  ok(sub { 1+1 }, 3);  # failure: '2' ne '3'
71*0Sstevel@tonic-gate
72*0Sstevel@tonic-gate  my @list = (0,0);
73*0Sstevel@tonic-gate  ok @list, 3, "\@list=".join(',',@list);      #extra notes
74*0Sstevel@tonic-gate  ok 'segmentation fault', '/(?i)success/';    #regex match
75*0Sstevel@tonic-gate
76*0Sstevel@tonic-gate  skip(
77*0Sstevel@tonic-gate    $^O eq 'MSWin' ? "Skip unless MSWin" : 0,  # whether to skip
78*0Sstevel@tonic-gate    $foo, $bar  # arguments just like for ok(...)
79*0Sstevel@tonic-gate  );
80*0Sstevel@tonic-gate  skip(
81*0Sstevel@tonic-gate    $^O eq 'MSWin' ? 0 : "Skip if MSWin",  # whether to skip
82*0Sstevel@tonic-gate    $foo, $bar  # arguments just like for ok(...)
83*0Sstevel@tonic-gate  );
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gate=head1 DESCRIPTION
86*0Sstevel@tonic-gate
87*0Sstevel@tonic-gateThis module simplifies the task of writing test files for Perl modules,
88*0Sstevel@tonic-gatesuch that their output is in the format that
89*0Sstevel@tonic-gateL<Test::Harness|Test::Harness> expects to see.
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate=head1 QUICK START GUIDE
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gateTo write a test for your new (and probably not even done) module, create
94*0Sstevel@tonic-gatea new file called F<t/test.t> (in a new F<t> directory). If you have
95*0Sstevel@tonic-gatemultiple test files, to test the "foo", "bar", and "baz" feature sets,
96*0Sstevel@tonic-gatethen feel free to call your files F<t/foo.t>, F<t/bar.t>, and
97*0Sstevel@tonic-gateF<t/baz.t>
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gate=head2 Functions
100*0Sstevel@tonic-gate
101*0Sstevel@tonic-gateThis module defines three public functions, C<plan(...)>, C<ok(...)>,
102*0Sstevel@tonic-gateand C<skip(...)>.  By default, all three are exported by
103*0Sstevel@tonic-gatethe C<use Test;> statement.
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gate=over 4
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate=item C<plan(...)>
108*0Sstevel@tonic-gate
109*0Sstevel@tonic-gate     BEGIN { plan %theplan; }
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gateThis should be the first thing you call in your test script.  It
112*0Sstevel@tonic-gatedeclares your testing plan, how many there will be, if any of them
113*0Sstevel@tonic-gateshould be allowed to fail, and so on.
114*0Sstevel@tonic-gate
115*0Sstevel@tonic-gateTypical usage is just:
116*0Sstevel@tonic-gate
117*0Sstevel@tonic-gate     use Test;
118*0Sstevel@tonic-gate     BEGIN { plan tests => 23 }
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gateThese are the things that you can put in the parameters to plan:
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gate=over
123*0Sstevel@tonic-gate
124*0Sstevel@tonic-gate=item C<tests =E<gt> I<number>>
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gateThe number of tests in your script.
127*0Sstevel@tonic-gateThis means all ok() and skip() calls.
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gate=item C<todo =E<gt> [I<1,5,14>]>
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gateA reference to a list of tests which are allowed to fail.
132*0Sstevel@tonic-gateSee L</TODO TESTS>.
133*0Sstevel@tonic-gate
134*0Sstevel@tonic-gate=item C<onfail =E<gt> sub { ... }>
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gate=item C<onfail =E<gt> \&some_sub>
137*0Sstevel@tonic-gate
138*0Sstevel@tonic-gateA subroutine reference to be run at the end of the test script, if
139*0Sstevel@tonic-gateany of the tests fail.  See L</ONFAIL>.
140*0Sstevel@tonic-gate
141*0Sstevel@tonic-gate=back
142*0Sstevel@tonic-gate
143*0Sstevel@tonic-gateYou must call C<plan(...)> once and only once.  You should call it
144*0Sstevel@tonic-gatein a C<BEGIN {...}> block, like so:
145*0Sstevel@tonic-gate
146*0Sstevel@tonic-gate     BEGIN { plan tests => 23 }
147*0Sstevel@tonic-gate
148*0Sstevel@tonic-gate=cut
149*0Sstevel@tonic-gate
150*0Sstevel@tonic-gatesub plan {
151*0Sstevel@tonic-gate    croak "Test::plan(%args): odd number of arguments" if @_ & 1;
152*0Sstevel@tonic-gate    croak "Test::plan(): should not be called more than once" if $planned;
153*0Sstevel@tonic-gate
154*0Sstevel@tonic-gate    local($\, $,);   # guard against -l and other things that screw with
155*0Sstevel@tonic-gate                     # print
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gate    _reset_globals();
158*0Sstevel@tonic-gate
159*0Sstevel@tonic-gate    _read_program( (caller)[1] );
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate    my $max=0;
162*0Sstevel@tonic-gate    for (my $x=0; $x < @_; $x+=2) {
163*0Sstevel@tonic-gate	my ($k,$v) = @_[$x,$x+1];
164*0Sstevel@tonic-gate	if ($k =~ /^test(s)?$/) { $max = $v; }
165*0Sstevel@tonic-gate	elsif ($k eq 'todo' or
166*0Sstevel@tonic-gate	       $k eq 'failok') { for (@$v) { $todo{$_}=1; }; }
167*0Sstevel@tonic-gate	elsif ($k eq 'onfail') {
168*0Sstevel@tonic-gate	    ref $v eq 'CODE' or croak "Test::plan(onfail => $v): must be CODE";
169*0Sstevel@tonic-gate	    $ONFAIL = $v;
170*0Sstevel@tonic-gate	}
171*0Sstevel@tonic-gate	else { carp "Test::plan(): skipping unrecognized directive '$k'" }
172*0Sstevel@tonic-gate    }
173*0Sstevel@tonic-gate    my @todo = sort { $a <=> $b } keys %todo;
174*0Sstevel@tonic-gate    if (@todo) {
175*0Sstevel@tonic-gate	print $TESTOUT "1..$max todo ".join(' ', @todo).";\n";
176*0Sstevel@tonic-gate    } else {
177*0Sstevel@tonic-gate	print $TESTOUT "1..$max\n";
178*0Sstevel@tonic-gate    }
179*0Sstevel@tonic-gate    ++$planned;
180*0Sstevel@tonic-gate    print $TESTOUT "# Running under perl version $] for $^O",
181*0Sstevel@tonic-gate      (chr(65) eq 'A') ? "\n" : " in a non-ASCII world\n";
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate    print $TESTOUT "# Win32::BuildNumber ", &Win32::BuildNumber(), "\n"
184*0Sstevel@tonic-gate      if defined(&Win32::BuildNumber) and defined &Win32::BuildNumber();
185*0Sstevel@tonic-gate
186*0Sstevel@tonic-gate    print $TESTOUT "# MacPerl version $MacPerl::Version\n"
187*0Sstevel@tonic-gate      if defined $MacPerl::Version;
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate    printf $TESTOUT
190*0Sstevel@tonic-gate      "# Current time local: %s\n# Current time GMT:   %s\n",
191*0Sstevel@tonic-gate      scalar(localtime($^T)), scalar(gmtime($^T));
192*0Sstevel@tonic-gate
193*0Sstevel@tonic-gate    print $TESTOUT "# Using Test.pm version $VERSION\n";
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate    # Retval never used:
196*0Sstevel@tonic-gate    return undef;
197*0Sstevel@tonic-gate}
198*0Sstevel@tonic-gate
199*0Sstevel@tonic-gatesub _read_program {
200*0Sstevel@tonic-gate  my($file) = shift;
201*0Sstevel@tonic-gate  return unless defined $file and length $file
202*0Sstevel@tonic-gate    and -e $file and -f _ and -r _;
203*0Sstevel@tonic-gate  open(SOURCEFILE, "<$file") || return;
204*0Sstevel@tonic-gate  $Program_Lines{$file} = [<SOURCEFILE>];
205*0Sstevel@tonic-gate  close(SOURCEFILE);
206*0Sstevel@tonic-gate
207*0Sstevel@tonic-gate  foreach my $x (@{$Program_Lines{$file}})
208*0Sstevel@tonic-gate   { $x =~ tr/\cm\cj\n\r//d }
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gate  unshift @{$Program_Lines{$file}}, '';
211*0Sstevel@tonic-gate  return 1;
212*0Sstevel@tonic-gate}
213*0Sstevel@tonic-gate
214*0Sstevel@tonic-gate=begin _private
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gate=item B<_to_value>
217*0Sstevel@tonic-gate
218*0Sstevel@tonic-gate  my $value = _to_value($input);
219*0Sstevel@tonic-gate
220*0Sstevel@tonic-gateConverts an C<ok> parameter to its value.  Typically this just means
221*0Sstevel@tonic-gaterunning it, if it's a code reference.  You should run all inputted
222*0Sstevel@tonic-gatevalues through this.
223*0Sstevel@tonic-gate
224*0Sstevel@tonic-gate=cut
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gatesub _to_value {
227*0Sstevel@tonic-gate    my ($v) = @_;
228*0Sstevel@tonic-gate    return (ref $v or '') eq 'CODE' ? $v->() : $v;
229*0Sstevel@tonic-gate}
230*0Sstevel@tonic-gate
231*0Sstevel@tonic-gate=end _private
232*0Sstevel@tonic-gate
233*0Sstevel@tonic-gate=item C<ok(...)>
234*0Sstevel@tonic-gate
235*0Sstevel@tonic-gate  ok(1 + 1 == 2);
236*0Sstevel@tonic-gate  ok($have, $expect);
237*0Sstevel@tonic-gate  ok($have, $expect, $diagnostics);
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gateThis function is the reason for C<Test>'s existence.  It's
240*0Sstevel@tonic-gatethe basic function that
241*0Sstevel@tonic-gatehandles printing "C<ok>" or "C<not ok>", along with the
242*0Sstevel@tonic-gatecurrent test number.  (That's what C<Test::Harness> wants to see.)
243*0Sstevel@tonic-gate
244*0Sstevel@tonic-gateIn its most basic usage, C<ok(...)> simply takes a single scalar
245*0Sstevel@tonic-gateexpression.  If its value is true, the test passes; if false,
246*0Sstevel@tonic-gatethe test fails.  Examples:
247*0Sstevel@tonic-gate
248*0Sstevel@tonic-gate    # Examples of ok(scalar)
249*0Sstevel@tonic-gate
250*0Sstevel@tonic-gate    ok( 1 + 1 == 2 );           # ok if 1 + 1 == 2
251*0Sstevel@tonic-gate    ok( $foo =~ /bar/ );        # ok if $foo contains 'bar'
252*0Sstevel@tonic-gate    ok( baz($x + $y) eq 'Armondo' );    # ok if baz($x + $y) returns
253*0Sstevel@tonic-gate                                        # 'Armondo'
254*0Sstevel@tonic-gate    ok( @a == @b );             # ok if @a and @b are the same length
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gateThe expression is evaluated in scalar context.  So the following will
257*0Sstevel@tonic-gatework:
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gate    ok( @stuff );                       # ok if @stuff has any elements
260*0Sstevel@tonic-gate    ok( !grep !defined $_, @stuff );    # ok if everything in @stuff is
261*0Sstevel@tonic-gate                                        # defined.
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gateA special case is if the expression is a subroutine reference (in either
264*0Sstevel@tonic-gateC<sub {...}> syntax or C<\&foo> syntax).  In
265*0Sstevel@tonic-gatethat case, it is executed and its value (true or false) determines if
266*0Sstevel@tonic-gatethe test passes or fails.  For example,
267*0Sstevel@tonic-gate
268*0Sstevel@tonic-gate    ok( sub {   # See whether sleep works at least passably
269*0Sstevel@tonic-gate      my $start_time = time;
270*0Sstevel@tonic-gate      sleep 5;
271*0Sstevel@tonic-gate      time() - $start_time  >= 4
272*0Sstevel@tonic-gate    });
273*0Sstevel@tonic-gate
274*0Sstevel@tonic-gateIn its two-argument form, C<ok(I<arg1>,I<arg2>)> compares the two scalar
275*0Sstevel@tonic-gatevalues to see if they equal.  (The equality is checked with C<eq>).
276*0Sstevel@tonic-gate
277*0Sstevel@tonic-gate    # Example of ok(scalar, scalar)
278*0Sstevel@tonic-gate
279*0Sstevel@tonic-gate    ok( "this", "that" );               # not ok, 'this' ne 'that'
280*0Sstevel@tonic-gate
281*0Sstevel@tonic-gateIf either (or both!) is a subroutine reference, it is run and used
282*0Sstevel@tonic-gateas the value for comparing.  For example:
283*0Sstevel@tonic-gate
284*0Sstevel@tonic-gate    ok 4, sub {
285*0Sstevel@tonic-gate        open(OUT, ">x.dat") || die $!;
286*0Sstevel@tonic-gate        print OUT "\x{e000}";
287*0Sstevel@tonic-gate        close OUT;
288*0Sstevel@tonic-gate        my $bytecount = -s 'x.dat';
289*0Sstevel@tonic-gate        unlink 'x.dat' or warn "Can't unlink : $!";
290*0Sstevel@tonic-gate        return $bytecount;
291*0Sstevel@tonic-gate      },
292*0Sstevel@tonic-gate    ;
293*0Sstevel@tonic-gate
294*0Sstevel@tonic-gateThe above test passes two values to C<ok(arg1, arg2)> -- the first is
295*0Sstevel@tonic-gatethe number 4, and the second is a coderef. Before C<ok> compares them,
296*0Sstevel@tonic-gateit calls the coderef, and uses its return value as the real value of
297*0Sstevel@tonic-gatethis parameter. Assuming that C<$bytecount> returns 4, C<ok> ends up
298*0Sstevel@tonic-gatetesting C<4 eq 4>. Since that's true, this test passes.
299*0Sstevel@tonic-gate
300*0Sstevel@tonic-gateIf C<arg2> is either a regex object (i.e., C<qr/.../>) or a string
301*0Sstevel@tonic-gatethat I<looks like> a regex (e.g., C<'/foo/'>), then
302*0Sstevel@tonic-gateC<ok(I<arg1>,I<arg2>)> will perform a pattern
303*0Sstevel@tonic-gatematch against it, instead of using C<eq>.
304*0Sstevel@tonic-gate
305*0Sstevel@tonic-gate    ok( 'JaffO', '/Jaff/' );    # ok, 'JaffO' =~ /Jaff/
306*0Sstevel@tonic-gate    ok( 'JaffO', qr/Jaff/ );    # ok, 'JaffO' =~ qr/Jaff/;
307*0Sstevel@tonic-gate    ok( 'JaffO', '/(?i)jaff/ ); # ok, 'JaffO' =~ /jaff/i;
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gateFinally, you can append an optional third argument, in
310*0Sstevel@tonic-gateC<ok(I<arg1>,I<arg2>, I<note>)>, where I<note> is a string value that
311*0Sstevel@tonic-gatewill be printed if the test fails.  This should be some useful
312*0Sstevel@tonic-gateinformation about the test, pertaining to why it failed, and/or
313*0Sstevel@tonic-gatea description of the test.  For example:
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate    ok( grep($_ eq 'something unique', @stuff), 1,
316*0Sstevel@tonic-gate        "Something that should be unique isn't!\n".
317*0Sstevel@tonic-gate        '@stuff = '.join ', ', @stuff
318*0Sstevel@tonic-gate      );
319*0Sstevel@tonic-gate
320*0Sstevel@tonic-gateUnfortunately, a note cannot be used with the single argument
321*0Sstevel@tonic-gatestyle of C<ok()>.  That is, if you try C<ok(I<arg1>, I<note>)>, then
322*0Sstevel@tonic-gateC<Test> will interpret this as C<ok(I<arg1>, I<arg2>)>, and probably
323*0Sstevel@tonic-gateend up testing C<I<arg1> eq I<arg2>> -- and that's not what you want!
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gateAll of the above special cases can occasionally cause some
326*0Sstevel@tonic-gateproblems.  See L</BUGS and CAVEATS>.
327*0Sstevel@tonic-gate
328*0Sstevel@tonic-gate=cut
329*0Sstevel@tonic-gate
330*0Sstevel@tonic-gate# A past maintainer of this module said:
331*0Sstevel@tonic-gate# <<ok(...)'s special handling of subroutine references is an unfortunate
332*0Sstevel@tonic-gate#   "feature" that can't be removed due to compatibility.>>
333*0Sstevel@tonic-gate#
334*0Sstevel@tonic-gate
335*0Sstevel@tonic-gatesub ok ($;$$) {
336*0Sstevel@tonic-gate    croak "ok: plan before you test!" if !$planned;
337*0Sstevel@tonic-gate
338*0Sstevel@tonic-gate    local($\,$,);   # guard against -l and other things that screw with
339*0Sstevel@tonic-gate                    # print
340*0Sstevel@tonic-gate
341*0Sstevel@tonic-gate    my ($pkg,$file,$line) = caller($TestLevel);
342*0Sstevel@tonic-gate    my $repetition = ++$history{"$file:$line"};
343*0Sstevel@tonic-gate    my $context = ("$file at line $line".
344*0Sstevel@tonic-gate		   ($repetition > 1 ? " fail \#$repetition" : ''));
345*0Sstevel@tonic-gate
346*0Sstevel@tonic-gate    # Are we comparing two values?
347*0Sstevel@tonic-gate    my $compare = 0;
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate    my $ok=0;
350*0Sstevel@tonic-gate    my $result = _to_value(shift);
351*0Sstevel@tonic-gate    my ($expected,$diag,$isregex,$regex);
352*0Sstevel@tonic-gate    if (@_ == 0) {
353*0Sstevel@tonic-gate	$ok = $result;
354*0Sstevel@tonic-gate    } else {
355*0Sstevel@tonic-gate        $compare = 1;
356*0Sstevel@tonic-gate	$expected = _to_value(shift);
357*0Sstevel@tonic-gate	if (!defined $expected) {
358*0Sstevel@tonic-gate	    $ok = !defined $result;
359*0Sstevel@tonic-gate	} elsif (!defined $result) {
360*0Sstevel@tonic-gate	    $ok = 0;
361*0Sstevel@tonic-gate	} elsif ((ref($expected)||'') eq 'Regexp') {
362*0Sstevel@tonic-gate	    $ok = $result =~ /$expected/;
363*0Sstevel@tonic-gate            $regex = $expected;
364*0Sstevel@tonic-gate	} elsif (($regex) = ($expected =~ m,^ / (.+) / $,sx) or
365*0Sstevel@tonic-gate	    (undef, $regex) = ($expected =~ m,^ m([^\w\s]) (.+) \1 $,sx)) {
366*0Sstevel@tonic-gate	    $ok = $result =~ /$regex/;
367*0Sstevel@tonic-gate	} else {
368*0Sstevel@tonic-gate	    $ok = $result eq $expected;
369*0Sstevel@tonic-gate	}
370*0Sstevel@tonic-gate    }
371*0Sstevel@tonic-gate    my $todo = $todo{$ntest};
372*0Sstevel@tonic-gate    if ($todo and $ok) {
373*0Sstevel@tonic-gate	$context .= ' TODO?!' if $todo;
374*0Sstevel@tonic-gate	print $TESTOUT "ok $ntest # ($context)\n";
375*0Sstevel@tonic-gate    } else {
376*0Sstevel@tonic-gate        # Issuing two seperate prints() causes problems on VMS.
377*0Sstevel@tonic-gate        if (!$ok) {
378*0Sstevel@tonic-gate            print $TESTOUT "not ok $ntest\n";
379*0Sstevel@tonic-gate        }
380*0Sstevel@tonic-gate	else {
381*0Sstevel@tonic-gate            print $TESTOUT "ok $ntest\n";
382*0Sstevel@tonic-gate        }
383*0Sstevel@tonic-gate
384*0Sstevel@tonic-gate	if (!$ok) {
385*0Sstevel@tonic-gate	    my $detail = { 'repetition' => $repetition, 'package' => $pkg,
386*0Sstevel@tonic-gate			   'result' => $result, 'todo' => $todo };
387*0Sstevel@tonic-gate	    $$detail{expected} = $expected if defined $expected;
388*0Sstevel@tonic-gate
389*0Sstevel@tonic-gate            # Get the user's diagnostic, protecting against multi-line
390*0Sstevel@tonic-gate            # diagnostics.
391*0Sstevel@tonic-gate	    $diag = $$detail{diagnostic} = _to_value(shift) if @_;
392*0Sstevel@tonic-gate            $diag =~ s/\n/\n#/g if defined $diag;
393*0Sstevel@tonic-gate
394*0Sstevel@tonic-gate	    $context .= ' *TODO*' if $todo;
395*0Sstevel@tonic-gate	    if (!$compare) {
396*0Sstevel@tonic-gate		if (!$diag) {
397*0Sstevel@tonic-gate		    print $TESTERR "# Failed test $ntest in $context\n";
398*0Sstevel@tonic-gate		} else {
399*0Sstevel@tonic-gate		    print $TESTERR "# Failed test $ntest in $context: $diag\n";
400*0Sstevel@tonic-gate		}
401*0Sstevel@tonic-gate	    } else {
402*0Sstevel@tonic-gate		my $prefix = "Test $ntest";
403*0Sstevel@tonic-gate		print $TESTERR "# $prefix got: ".
404*0Sstevel@tonic-gate		    (defined $result? "'$result'":'<UNDEF>')." ($context)\n";
405*0Sstevel@tonic-gate		$prefix = ' ' x (length($prefix) - 5);
406*0Sstevel@tonic-gate		if (defined $regex) {
407*0Sstevel@tonic-gate		    $expected = 'qr{'.$regex.'}';
408*0Sstevel@tonic-gate		}
409*0Sstevel@tonic-gate                elsif (defined $expected) {
410*0Sstevel@tonic-gate		    $expected = "'$expected'";
411*0Sstevel@tonic-gate		}
412*0Sstevel@tonic-gate                else {
413*0Sstevel@tonic-gate                    $expected = '<UNDEF>';
414*0Sstevel@tonic-gate                }
415*0Sstevel@tonic-gate		if (!$diag) {
416*0Sstevel@tonic-gate		    print $TESTERR "# $prefix Expected: $expected\n";
417*0Sstevel@tonic-gate		} else {
418*0Sstevel@tonic-gate		    print $TESTERR "# $prefix Expected: $expected ($diag)\n";
419*0Sstevel@tonic-gate		}
420*0Sstevel@tonic-gate	    }
421*0Sstevel@tonic-gate
422*0Sstevel@tonic-gate            if(defined $Program_Lines{$file}[$line]) {
423*0Sstevel@tonic-gate                print $TESTERR
424*0Sstevel@tonic-gate                  "#  $file line $line is: $Program_Lines{$file}[$line]\n"
425*0Sstevel@tonic-gate                 if
426*0Sstevel@tonic-gate                  $Program_Lines{$file}[$line] =~ m/[^\s\#\(\)\{\}\[\]\;]/
427*0Sstevel@tonic-gate                   # Otherwise it's a pretty uninteresting line!
428*0Sstevel@tonic-gate                ;
429*0Sstevel@tonic-gate
430*0Sstevel@tonic-gate                undef $Program_Lines{$file}[$line];
431*0Sstevel@tonic-gate                 # So we won't repeat it.
432*0Sstevel@tonic-gate            }
433*0Sstevel@tonic-gate
434*0Sstevel@tonic-gate	    push @FAILDETAIL, $detail;
435*0Sstevel@tonic-gate	}
436*0Sstevel@tonic-gate    }
437*0Sstevel@tonic-gate    ++ $ntest;
438*0Sstevel@tonic-gate    $ok;
439*0Sstevel@tonic-gate}
440*0Sstevel@tonic-gate
441*0Sstevel@tonic-gate=item C<skip(I<skip_if_true>, I<args...>)>
442*0Sstevel@tonic-gate
443*0Sstevel@tonic-gateThis is used for tests that under some conditions can be skipped.  It's
444*0Sstevel@tonic-gatebasically equivalent to:
445*0Sstevel@tonic-gate
446*0Sstevel@tonic-gate  if( $skip_if_true ) {
447*0Sstevel@tonic-gate    ok(1);
448*0Sstevel@tonic-gate  } else {
449*0Sstevel@tonic-gate    ok( args... );
450*0Sstevel@tonic-gate  }
451*0Sstevel@tonic-gate
452*0Sstevel@tonic-gate...except that the C<ok(1)> emits not just "C<ok I<testnum>>" but
453*0Sstevel@tonic-gateactually "C<ok I<testnum> # I<skip_if_true_value>>".
454*0Sstevel@tonic-gate
455*0Sstevel@tonic-gateThe arguments after the I<skip_if_true> are what is fed to C<ok(...)> if
456*0Sstevel@tonic-gatethis test isn't skipped.
457*0Sstevel@tonic-gate
458*0Sstevel@tonic-gateExample usage:
459*0Sstevel@tonic-gate
460*0Sstevel@tonic-gate  my $if_MSWin =
461*0Sstevel@tonic-gate    $^O eq 'MSWin' ? 'Skip if under MSWin' : '';
462*0Sstevel@tonic-gate
463*0Sstevel@tonic-gate  # A test to be run EXCEPT under MSWin:
464*0Sstevel@tonic-gate  skip($if_MSWin, thing($foo), thing($bar) );
465*0Sstevel@tonic-gate
466*0Sstevel@tonic-gateOr, going the other way:
467*0Sstevel@tonic-gate
468*0Sstevel@tonic-gate  my $unless_MSWin =
469*0Sstevel@tonic-gate    $^O eq 'MSWin' ? 'Skip unless under MSWin' : '';
470*0Sstevel@tonic-gate
471*0Sstevel@tonic-gate  # A test to be run EXCEPT under MSWin:
472*0Sstevel@tonic-gate  skip($unless_MSWin, thing($foo), thing($bar) );
473*0Sstevel@tonic-gate
474*0Sstevel@tonic-gateThe tricky thing to remember is that the first parameter is true if
475*0Sstevel@tonic-gateyou want to I<skip> the test, not I<run> it; and it also doubles as a
476*0Sstevel@tonic-gatenote about why it's being skipped. So in the first codeblock above, read
477*0Sstevel@tonic-gatethe code as "skip if MSWin -- (otherwise) test whether C<thing($foo)> is
478*0Sstevel@tonic-gateC<thing($bar)>" or for the second case, "skip unless MSWin...".
479*0Sstevel@tonic-gate
480*0Sstevel@tonic-gateAlso, when your I<skip_if_reason> string is true, it really should (for
481*0Sstevel@tonic-gatebackwards compatibility with older Test.pm versions) start with the
482*0Sstevel@tonic-gatestring "Skip", as shown in the above examples.
483*0Sstevel@tonic-gate
484*0Sstevel@tonic-gateNote that in the above cases, C<thing($foo)> and C<thing($bar)>
485*0Sstevel@tonic-gateI<are> evaluated -- but as long as the C<skip_if_true> is true,
486*0Sstevel@tonic-gatethen we C<skip(...)> just tosses out their value (i.e., not
487*0Sstevel@tonic-gatebothering to treat them like values to C<ok(...)>.  But if
488*0Sstevel@tonic-gateyou need to I<not> eval the arguments when skipping the
489*0Sstevel@tonic-gatetest, use
490*0Sstevel@tonic-gatethis format:
491*0Sstevel@tonic-gate
492*0Sstevel@tonic-gate  skip( $unless_MSWin,
493*0Sstevel@tonic-gate    sub {
494*0Sstevel@tonic-gate      # This code returns true if the test passes.
495*0Sstevel@tonic-gate      # (But it doesn't even get called if the test is skipped.)
496*0Sstevel@tonic-gate      thing($foo) eq thing($bar)
497*0Sstevel@tonic-gate    }
498*0Sstevel@tonic-gate  );
499*0Sstevel@tonic-gate
500*0Sstevel@tonic-gateor even this, which is basically equivalent:
501*0Sstevel@tonic-gate
502*0Sstevel@tonic-gate  skip( $unless_MSWin,
503*0Sstevel@tonic-gate    sub { thing($foo) }, sub { thing($bar) }
504*0Sstevel@tonic-gate  );
505*0Sstevel@tonic-gate
506*0Sstevel@tonic-gateThat is, both are like this:
507*0Sstevel@tonic-gate
508*0Sstevel@tonic-gate  if( $unless_MSWin ) {
509*0Sstevel@tonic-gate    ok(1);  # but it actually appends "# $unless_MSWin"
510*0Sstevel@tonic-gate            #  so that Test::Harness can tell it's a skip
511*0Sstevel@tonic-gate  } else {
512*0Sstevel@tonic-gate    # Not skipping, so actually call and evaluate...
513*0Sstevel@tonic-gate    ok( sub { thing($foo) }, sub { thing($bar) } );
514*0Sstevel@tonic-gate  }
515*0Sstevel@tonic-gate
516*0Sstevel@tonic-gate=cut
517*0Sstevel@tonic-gate
518*0Sstevel@tonic-gatesub skip ($;$$$) {
519*0Sstevel@tonic-gate    local($\, $,);   # guard against -l and other things that screw with
520*0Sstevel@tonic-gate                     # print
521*0Sstevel@tonic-gate
522*0Sstevel@tonic-gate    my $whyskip = _to_value(shift);
523*0Sstevel@tonic-gate    if (!@_ or $whyskip) {
524*0Sstevel@tonic-gate	$whyskip = '' if $whyskip =~ m/^\d+$/;
525*0Sstevel@tonic-gate        $whyskip =~ s/^[Ss]kip(?:\s+|$)//;  # backwards compatibility, old
526*0Sstevel@tonic-gate                                            # versions required the reason
527*0Sstevel@tonic-gate                                            # to start with 'skip'
528*0Sstevel@tonic-gate        # We print in one shot for VMSy reasons.
529*0Sstevel@tonic-gate        my $ok = "ok $ntest # skip";
530*0Sstevel@tonic-gate        $ok .= " $whyskip" if length $whyskip;
531*0Sstevel@tonic-gate        $ok .= "\n";
532*0Sstevel@tonic-gate        print $TESTOUT $ok;
533*0Sstevel@tonic-gate        ++ $ntest;
534*0Sstevel@tonic-gate        return 1;
535*0Sstevel@tonic-gate    } else {
536*0Sstevel@tonic-gate        # backwards compatiblity (I think).  skip() used to be
537*0Sstevel@tonic-gate        # called like ok(), which is weird.  I haven't decided what to do with
538*0Sstevel@tonic-gate        # this yet.
539*0Sstevel@tonic-gate#        warn <<WARN if $^W;
540*0Sstevel@tonic-gate#This looks like a skip() using the very old interface.  Please upgrade to
541*0Sstevel@tonic-gate#the documented interface as this has been deprecated.
542*0Sstevel@tonic-gate#WARN
543*0Sstevel@tonic-gate
544*0Sstevel@tonic-gate	local($TestLevel) = $TestLevel+1;  #to ignore this stack frame
545*0Sstevel@tonic-gate        return &ok(@_);
546*0Sstevel@tonic-gate    }
547*0Sstevel@tonic-gate}
548*0Sstevel@tonic-gate
549*0Sstevel@tonic-gate=back
550*0Sstevel@tonic-gate
551*0Sstevel@tonic-gate=cut
552*0Sstevel@tonic-gate
553*0Sstevel@tonic-gateEND {
554*0Sstevel@tonic-gate    $ONFAIL->(\@FAILDETAIL) if @FAILDETAIL && $ONFAIL;
555*0Sstevel@tonic-gate}
556*0Sstevel@tonic-gate
557*0Sstevel@tonic-gate1;
558*0Sstevel@tonic-gate__END__
559*0Sstevel@tonic-gate
560*0Sstevel@tonic-gate=head1 TEST TYPES
561*0Sstevel@tonic-gate
562*0Sstevel@tonic-gate=over 4
563*0Sstevel@tonic-gate
564*0Sstevel@tonic-gate=item * NORMAL TESTS
565*0Sstevel@tonic-gate
566*0Sstevel@tonic-gateThese tests are expected to succeed.  Usually, most or all of your tests
567*0Sstevel@tonic-gateare in this category.  If a normal test doesn't succeed, then that
568*0Sstevel@tonic-gatemeans that something is I<wrong>.
569*0Sstevel@tonic-gate
570*0Sstevel@tonic-gate=item * SKIPPED TESTS
571*0Sstevel@tonic-gate
572*0Sstevel@tonic-gateThe C<skip(...)> function is for tests that might or might not be
573*0Sstevel@tonic-gatepossible to run, depending
574*0Sstevel@tonic-gateon the availability of platform-specific features.  The first argument
575*0Sstevel@tonic-gateshould evaluate to true (think "yes, please skip") if the required
576*0Sstevel@tonic-gatefeature is I<not> available.  After the first argument, C<skip(...)> works
577*0Sstevel@tonic-gateexactly the same way as C<ok(...)> does.
578*0Sstevel@tonic-gate
579*0Sstevel@tonic-gate=item * TODO TESTS
580*0Sstevel@tonic-gate
581*0Sstevel@tonic-gateTODO tests are designed for maintaining an B<executable TODO list>.
582*0Sstevel@tonic-gateThese tests are I<expected to fail.>  If a TODO test does succeed,
583*0Sstevel@tonic-gatethen the feature in question shouldn't be on the TODO list, now
584*0Sstevel@tonic-gateshould it?
585*0Sstevel@tonic-gate
586*0Sstevel@tonic-gatePackages should NOT be released with succeeding TODO tests.  As soon
587*0Sstevel@tonic-gateas a TODO test starts working, it should be promoted to a normal test,
588*0Sstevel@tonic-gateand the newly working feature should be documented in the release
589*0Sstevel@tonic-gatenotes or in the change log.
590*0Sstevel@tonic-gate
591*0Sstevel@tonic-gate=back
592*0Sstevel@tonic-gate
593*0Sstevel@tonic-gate=head1 ONFAIL
594*0Sstevel@tonic-gate
595*0Sstevel@tonic-gate  BEGIN { plan test => 4, onfail => sub { warn "CALL 911!" } }
596*0Sstevel@tonic-gate
597*0Sstevel@tonic-gateAlthough test failures should be enough, extra diagnostics can be
598*0Sstevel@tonic-gatetriggered at the end of a test run.  C<onfail> is passed an array ref
599*0Sstevel@tonic-gateof hash refs that describe each test failure.  Each hash will contain
600*0Sstevel@tonic-gateat least the following fields: C<package>, C<repetition>, and
601*0Sstevel@tonic-gateC<result>.  (The file, line, and test number are not included because
602*0Sstevel@tonic-gatetheir correspondence to a particular test is tenuous.)  If the test
603*0Sstevel@tonic-gatehad an expected value or a diagnostic (or "note") string, these will also be
604*0Sstevel@tonic-gateincluded.
605*0Sstevel@tonic-gate
606*0Sstevel@tonic-gateThe I<optional> C<onfail> hook might be used simply to print out the
607*0Sstevel@tonic-gateversion of your package and/or how to report problems.  It might also
608*0Sstevel@tonic-gatebe used to generate extremely sophisticated diagnostics for a
609*0Sstevel@tonic-gateparticularly bizarre test failure.  However it's not a panacea.  Core
610*0Sstevel@tonic-gatedumps or other unrecoverable errors prevent the C<onfail> hook from
611*0Sstevel@tonic-gaterunning.  (It is run inside an C<END> block.)  Besides, C<onfail> is
612*0Sstevel@tonic-gateprobably over-kill in most cases.  (Your test code should be simpler
613*0Sstevel@tonic-gatethan the code it is testing, yes?)
614*0Sstevel@tonic-gate
615*0Sstevel@tonic-gate
616*0Sstevel@tonic-gate=head1 BUGS and CAVEATS
617*0Sstevel@tonic-gate
618*0Sstevel@tonic-gate=over
619*0Sstevel@tonic-gate
620*0Sstevel@tonic-gate=item *
621*0Sstevel@tonic-gate
622*0Sstevel@tonic-gateC<ok(...)>'s special handing of strings which look like they might be
623*0Sstevel@tonic-gateregexes can also cause unexpected behavior.  An innocent:
624*0Sstevel@tonic-gate
625*0Sstevel@tonic-gate    ok( $fileglob, '/path/to/some/*stuff/' );
626*0Sstevel@tonic-gate
627*0Sstevel@tonic-gatewill fail, since Test.pm considers the second argument to be a regex!
628*0Sstevel@tonic-gateThe best bet is to use the one-argument form:
629*0Sstevel@tonic-gate
630*0Sstevel@tonic-gate    ok( $fileglob eq '/path/to/some/*stuff/' );
631*0Sstevel@tonic-gate
632*0Sstevel@tonic-gate=item *
633*0Sstevel@tonic-gate
634*0Sstevel@tonic-gateC<ok(...)>'s use of string C<eq> can sometimes cause odd problems
635*0Sstevel@tonic-gatewhen comparing
636*0Sstevel@tonic-gatenumbers, especially if you're casting a string to a number:
637*0Sstevel@tonic-gate
638*0Sstevel@tonic-gate    $foo = "1.0";
639*0Sstevel@tonic-gate    ok( $foo, 1 );      # not ok, "1.0" ne 1
640*0Sstevel@tonic-gate
641*0Sstevel@tonic-gateYour best bet is to use the single argument form:
642*0Sstevel@tonic-gate
643*0Sstevel@tonic-gate    ok( $foo == 1 );    # ok "1.0" == 1
644*0Sstevel@tonic-gate
645*0Sstevel@tonic-gate=item *
646*0Sstevel@tonic-gate
647*0Sstevel@tonic-gateAs you may have inferred from the above documentation and examples,
648*0Sstevel@tonic-gateC<ok>'s prototype is C<($;$$)> (and, incidentally, C<skip>'s is
649*0Sstevel@tonic-gateC<($;$$$)>). This means, for example, that you can do C<ok @foo, @bar>
650*0Sstevel@tonic-gateto compare the I<size> of the two arrays. But don't be fooled into
651*0Sstevel@tonic-gatethinking that C<ok @foo, @bar> means a comparison of the contents of two
652*0Sstevel@tonic-gatearrays -- you're comparing I<just> the number of elements of each. It's
653*0Sstevel@tonic-gateso easy to make that mistake in reading C<ok @foo, @bar> that you might
654*0Sstevel@tonic-gatewant to be very explicit about it, and instead write C<ok scalar(@foo),
655*0Sstevel@tonic-gatescalar(@bar)>.
656*0Sstevel@tonic-gate
657*0Sstevel@tonic-gate=item *
658*0Sstevel@tonic-gate
659*0Sstevel@tonic-gateThis almost definitely doesn't do what you expect:
660*0Sstevel@tonic-gate
661*0Sstevel@tonic-gate     ok $thingy->can('some_method');
662*0Sstevel@tonic-gate
663*0Sstevel@tonic-gateWhy?  Because C<can> returns a coderef to mean "yes it can (and the
664*0Sstevel@tonic-gatemethod is this...)", and then C<ok> sees a coderef and thinks you're
665*0Sstevel@tonic-gatepassing a function that you want it to call and consider the truth of
666*0Sstevel@tonic-gatethe result of!  I.e., just like:
667*0Sstevel@tonic-gate
668*0Sstevel@tonic-gate     ok $thingy->can('some_method')->();
669*0Sstevel@tonic-gate
670*0Sstevel@tonic-gateWhat you probably want instead is this:
671*0Sstevel@tonic-gate
672*0Sstevel@tonic-gate     ok $thingy->can('some_method') && 1;
673*0Sstevel@tonic-gate
674*0Sstevel@tonic-gateIf the C<can> returns false, then that is passed to C<ok>.  If it
675*0Sstevel@tonic-gatereturns true, then the larger expression S<< C<<
676*0Sstevel@tonic-gate$thingy->can('some_method') && 1 >> >> returns 1, which C<ok> sees as
677*0Sstevel@tonic-gatea simple signal of success, as you would expect.
678*0Sstevel@tonic-gate
679*0Sstevel@tonic-gate
680*0Sstevel@tonic-gate=item *
681*0Sstevel@tonic-gate
682*0Sstevel@tonic-gateThe syntax for C<skip> is about the only way it can be, but it's still
683*0Sstevel@tonic-gatequite confusing.  Just start with the above examples and you'll
684*0Sstevel@tonic-gatebe okay.
685*0Sstevel@tonic-gate
686*0Sstevel@tonic-gateMoreover, users may expect this:
687*0Sstevel@tonic-gate
688*0Sstevel@tonic-gate  skip $unless_mswin, foo($bar), baz($quux);
689*0Sstevel@tonic-gate
690*0Sstevel@tonic-gateto not evaluate C<foo($bar)> and C<baz($quux)> when the test is being
691*0Sstevel@tonic-gateskipped.  But in reality, they I<are> evaluated, but C<skip> just won't
692*0Sstevel@tonic-gatebother comparing them if C<$unless_mswin> is true.
693*0Sstevel@tonic-gate
694*0Sstevel@tonic-gateYou could do this:
695*0Sstevel@tonic-gate
696*0Sstevel@tonic-gate  skip $unless_mswin, sub{foo($bar)}, sub{baz($quux)};
697*0Sstevel@tonic-gate
698*0Sstevel@tonic-gateBut that's not terribly pretty.  You may find it simpler or clearer in
699*0Sstevel@tonic-gatethe long run to just do things like this:
700*0Sstevel@tonic-gate
701*0Sstevel@tonic-gate  if( $^O =~ m/MSWin/ ) {
702*0Sstevel@tonic-gate    print "# Yay, we're under $^O\n";
703*0Sstevel@tonic-gate    ok foo($bar), baz($quux);
704*0Sstevel@tonic-gate    ok thing($whatever), baz($stuff);
705*0Sstevel@tonic-gate    ok blorp($quux, $whatever);
706*0Sstevel@tonic-gate    ok foo($barzbarz), thang($quux);
707*0Sstevel@tonic-gate  } else {
708*0Sstevel@tonic-gate    print "# Feh, we're under $^O.  Watch me skip some tests...\n";
709*0Sstevel@tonic-gate    for(1 .. 4) { skip "Skip unless under MSWin" }
710*0Sstevel@tonic-gate  }
711*0Sstevel@tonic-gate
712*0Sstevel@tonic-gateBut be quite sure that C<ok> is called exactly as many times in the
713*0Sstevel@tonic-gatefirst block as C<skip> is called in the second block.
714*0Sstevel@tonic-gate
715*0Sstevel@tonic-gate=back
716*0Sstevel@tonic-gate
717*0Sstevel@tonic-gate=head1 NOTE
718*0Sstevel@tonic-gate
719*0Sstevel@tonic-gateA past developer of this module once said that it was no longer being
720*0Sstevel@tonic-gateactively developed.  However, rumors of its demise were greatly
721*0Sstevel@tonic-gateexaggerated.  Feedback and suggestions are quite welcome.
722*0Sstevel@tonic-gate
723*0Sstevel@tonic-gateBe aware that the main value of this module is its simplicity.  Note
724*0Sstevel@tonic-gatethat there are already more ambitious modules out there, such as
725*0Sstevel@tonic-gateL<Test::More> and L<Test::Unit>.
726*0Sstevel@tonic-gate
727*0Sstevel@tonic-gate
728*0Sstevel@tonic-gate=head1 SEE ALSO
729*0Sstevel@tonic-gate
730*0Sstevel@tonic-gateL<Test::Harness>
731*0Sstevel@tonic-gate
732*0Sstevel@tonic-gateL<Test::Simple>, L<Test::More>, L<Devel::Cover>
733*0Sstevel@tonic-gate
734*0Sstevel@tonic-gateL<Test::Builder> for building your own testing library.
735*0Sstevel@tonic-gate
736*0Sstevel@tonic-gateL<Test::Unit> is an interesting XUnit-style testing library.
737*0Sstevel@tonic-gate
738*0Sstevel@tonic-gateL<Test::Inline> and L<SelfTest> let you embed tests in code.
739*0Sstevel@tonic-gate
740*0Sstevel@tonic-gate
741*0Sstevel@tonic-gate=head1 AUTHOR
742*0Sstevel@tonic-gate
743*0Sstevel@tonic-gateCopyright (c) 1998-2000 Joshua Nathaniel Pritikin.  All rights reserved.
744*0Sstevel@tonic-gate
745*0Sstevel@tonic-gateCopyright (c) 2001-2002 Michael G. Schwern.
746*0Sstevel@tonic-gate
747*0Sstevel@tonic-gateCopyright (c) 2002-2003 Sean M. Burke.
748*0Sstevel@tonic-gate
749*0Sstevel@tonic-gateCurrent maintainer: Sean M. Burke. E<lt>sburke@cpan.orgE<gt>
750*0Sstevel@tonic-gate
751*0Sstevel@tonic-gateThis package is free software and is provided "as is" without express
752*0Sstevel@tonic-gateor implied warranty.  It may be used, redistributed and/or modified
753*0Sstevel@tonic-gateunder the same terms as Perl itself.
754*0Sstevel@tonic-gate
755*0Sstevel@tonic-gate=cut
756*0Sstevel@tonic-gate
757*0Sstevel@tonic-gate# "Your mistake was a hidden intention."
758*0Sstevel@tonic-gate#  -- /Oblique Strategies/,  Brian Eno and Peter Schmidt
759