summaryrefslogtreecommitdiffstats
path: root/upstream/debian-unstable/man3/Test::Tutorial.3perl
diff options
context:
space:
mode:
Diffstat (limited to 'upstream/debian-unstable/man3/Test::Tutorial.3perl')
-rw-r--r--upstream/debian-unstable/man3/Test::Tutorial.3perl683
1 files changed, 683 insertions, 0 deletions
diff --git a/upstream/debian-unstable/man3/Test::Tutorial.3perl b/upstream/debian-unstable/man3/Test::Tutorial.3perl
new file mode 100644
index 00000000..1d8c4cf2
--- /dev/null
+++ b/upstream/debian-unstable/man3/Test::Tutorial.3perl
@@ -0,0 +1,683 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>.
+.ie n \{\
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+. if \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{\
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\" ========================================================================
+.\"
+.IX Title "Test::Tutorial 3perl"
+.TH Test::Tutorial 3perl 2024-01-12 "perl v5.38.2" "Perl Programmers Reference Guide"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH NAME
+Test::Tutorial \- A tutorial about writing really basic tests
+.SH DESCRIPTION
+.IX Header "DESCRIPTION"
+\&\fIAHHHHHHH!!!! NOT TESTING! Anything but testing!
+Beat me, whip me, send me to Detroit, but don't make
+me write tests!\fR
+.PP
+\&\fI*sob*\fR
+.PP
+\&\fIBesides, I don't know how to write the damned things.\fR
+.PP
+Is this you? Is writing tests right up there with writing
+documentation and having your fingernails pulled out? Did you open up
+a test and read
+.PP
+.Vb 1
+\& ######## We start with some black magic
+.Ve
+.PP
+and decide that's quite enough for you?
+.PP
+It's ok. That's all gone now. We've done all the black magic for
+you. And here are the tricks...
+.SS "Nuts and bolts of testing."
+.IX Subsection "Nuts and bolts of testing."
+Here's the most basic test program.
+.PP
+.Vb 1
+\& #!/usr/bin/perl \-w
+\&
+\& print "1..1\en";
+\&
+\& print 1 + 1 == 2 ? "ok 1\en" : "not ok 1\en";
+.Ve
+.PP
+Because 1 + 1 is 2, it prints:
+.PP
+.Vb 2
+\& 1..1
+\& ok 1
+.Ve
+.PP
+What this says is: \f(CW1..1\fR "I'm going to run one test." [1] \f(CW\*(C`ok 1\*(C'\fR
+"The first test passed". And that's about all magic there is to
+testing. Your basic unit of testing is the \fIok\fR. For each thing you
+test, an \f(CW\*(C`ok\*(C'\fR is printed. Simple. Test::Harness interprets your test
+results to determine if you succeeded or failed (more on that later).
+.PP
+Writing all these print statements rapidly gets tedious. Fortunately,
+there's Test::Simple. It has one function, \f(CWok()\fR.
+.PP
+.Vb 1
+\& #!/usr/bin/perl \-w
+\&
+\& use Test::Simple tests => 1;
+\&
+\& ok( 1 + 1 == 2 );
+.Ve
+.PP
+That does the same thing as the previous code. \f(CWok()\fR is the backbone
+of Perl testing, and we'll be using it instead of roll-your-own from
+here on. If \f(CWok()\fR gets a true value, the test passes. False, it
+fails.
+.PP
+.Vb 1
+\& #!/usr/bin/perl \-w
+\&
+\& use Test::Simple tests => 2;
+\& ok( 1 + 1 == 2 );
+\& ok( 2 + 2 == 5 );
+.Ve
+.PP
+From that comes:
+.PP
+.Vb 5
+\& 1..2
+\& ok 1
+\& not ok 2
+\& # Failed test (test.pl at line 5)
+\& # Looks like you failed 1 tests of 2.
+.Ve
+.PP
+\&\f(CW1..2\fR "I'm going to run two tests." This number is a \fIplan\fR. It helps to
+ensure your test program ran all the way through and didn't die or skip some
+tests. \f(CW\*(C`ok 1\*(C'\fR "The first test passed." \f(CW\*(C`not ok 2\*(C'\fR "The second test failed".
+Test::Simple helpfully prints out some extra commentary about your tests.
+.PP
+It's not scary. Come, hold my hand. We're going to give an example
+of testing a module. For our example, we'll be testing a date
+library, Date::ICal. It's on CPAN, so download a copy and follow
+along. [2]
+.SS "Where to start?"
+.IX Subsection "Where to start?"
+This is the hardest part of testing, where do you start? People often get
+overwhelmed at the apparent enormity of the task of testing a whole module.
+The best place to start is at the beginning. Date::ICal is an
+object-oriented module, and that means you start by making an object. Test
+\&\f(CWnew()\fR.
+.PP
+.Vb 1
+\& #!/usr/bin/perl \-w
+\&
+\& # assume these two lines are in all subsequent examples
+\& use strict;
+\& use warnings;
+\&
+\& use Test::Simple tests => 2;
+\&
+\& use Date::ICal;
+\&
+\& my $ical = Date::ICal\->new; # create an object
+\& ok( defined $ical ); # check that we got something
+\& ok( $ical\->isa(\*(AqDate::ICal\*(Aq) ); # and it\*(Aqs the right class
+.Ve
+.PP
+Run that and you should get:
+.PP
+.Vb 3
+\& 1..2
+\& ok 1
+\& ok 2
+.Ve
+.PP
+Congratulations! You've written your first useful test.
+.SS Names
+.IX Subsection "Names"
+That output isn't terribly descriptive, is it? When you have two tests you can
+figure out which one is #2, but what if you have 102 tests?
+.PP
+Each test can be given a little descriptive name as the second
+argument to \f(CWok()\fR.
+.PP
+.Vb 1
+\& use Test::Simple tests => 2;
+\&
+\& ok( defined $ical, \*(Aqnew() returned something\*(Aq );
+\& ok( $ical\->isa(\*(AqDate::ICal\*(Aq), " and it\*(Aqs the right class" );
+.Ve
+.PP
+Now you'll see:
+.PP
+.Vb 3
+\& 1..2
+\& ok 1 \- new() returned something
+\& ok 2 \- and it\*(Aqs the right class
+.Ve
+.SS "Test the manual"
+.IX Subsection "Test the manual"
+The simplest way to build up a decent testing suite is to just test what
+the manual says it does. [3] Let's pull something out of the
+"SYNOPSIS" in Date::ICal and test that all its bits work.
+.PP
+.Vb 1
+\& #!/usr/bin/perl \-w
+\&
+\& use Test::Simple tests => 8;
+\&
+\& use Date::ICal;
+\&
+\& $ical = Date::ICal\->new( year => 1964, month => 10, day => 16,
+\& hour => 16, min => 12, sec => 47,
+\& tz => \*(Aq0530\*(Aq );
+\&
+\& ok( defined $ical, \*(Aqnew() returned something\*(Aq );
+\& ok( $ical\->isa(\*(AqDate::ICal\*(Aq), " and it\*(Aqs the right class" );
+\& ok( $ical\->sec == 47, \*(Aq sec()\*(Aq );
+\& ok( $ical\->min == 12, \*(Aq min()\*(Aq );
+\& ok( $ical\->hour == 16, \*(Aq hour()\*(Aq );
+\& ok( $ical\->day == 17, \*(Aq day()\*(Aq );
+\& ok( $ical\->month == 10, \*(Aq month()\*(Aq );
+\& ok( $ical\->year == 1964, \*(Aq year()\*(Aq );
+.Ve
+.PP
+Run that and you get:
+.PP
+.Vb 11
+\& 1..8
+\& ok 1 \- new() returned something
+\& ok 2 \- and it\*(Aqs the right class
+\& ok 3 \- sec()
+\& ok 4 \- min()
+\& ok 5 \- hour()
+\& not ok 6 \- day()
+\& # Failed test (\- at line 16)
+\& ok 7 \- month()
+\& ok 8 \- year()
+\& # Looks like you failed 1 tests of 8.
+.Ve
+.PP
+Whoops, a failure! [4] Test::Simple helpfully lets us know on what line the
+failure occurred, but not much else. We were supposed to get 17, but we
+didn't. What did we get?? Dunno. You could re-run the test in the debugger
+or throw in some print statements to find out.
+.PP
+Instead, switch from Test::Simple to Test::More. Test::More
+does everything Test::Simple does, and more! In fact, Test::More does
+things \fIexactly\fR the way Test::Simple does. You can literally swap
+Test::Simple out and put Test::More in its place. That's just what
+we're going to do.
+.PP
+Test::More does more than Test::Simple. The most important difference at
+this point is it provides more informative ways to say "ok". Although you can
+write almost any test with a generic \f(CWok()\fR, it can't tell you what went
+wrong. The \f(CWis()\fR function lets us declare that something is supposed to be
+the same as something else:
+.PP
+.Vb 1
+\& use Test::More tests => 8;
+\&
+\& use Date::ICal;
+\&
+\& $ical = Date::ICal\->new( year => 1964, month => 10, day => 16,
+\& hour => 16, min => 12, sec => 47,
+\& tz => \*(Aq0530\*(Aq );
+\&
+\& ok( defined $ical, \*(Aqnew() returned something\*(Aq );
+\& ok( $ical\->isa(\*(AqDate::ICal\*(Aq), " and it\*(Aqs the right class" );
+\& is( $ical\->sec, 47, \*(Aq sec()\*(Aq );
+\& is( $ical\->min, 12, \*(Aq min()\*(Aq );
+\& is( $ical\->hour, 16, \*(Aq hour()\*(Aq );
+\& is( $ical\->day, 17, \*(Aq day()\*(Aq );
+\& is( $ical\->month, 10, \*(Aq month()\*(Aq );
+\& is( $ical\->year, 1964, \*(Aq year()\*(Aq );
+.Ve
+.PP
+"Is \f(CW\*(C`$ical\->sec\*(C'\fR 47?" "Is \f(CW\*(C`$ical\->min\*(C'\fR 12?" With \f(CWis()\fR in place,
+you get more information:
+.PP
+.Vb 10
+\& 1..8
+\& ok 1 \- new() returned something
+\& ok 2 \- and it\*(Aqs the right class
+\& ok 3 \- sec()
+\& ok 4 \- min()
+\& ok 5 \- hour()
+\& not ok 6 \- day()
+\& # Failed test (\- at line 16)
+\& # got: \*(Aq16\*(Aq
+\& # expected: \*(Aq17\*(Aq
+\& ok 7 \- month()
+\& ok 8 \- year()
+\& # Looks like you failed 1 tests of 8.
+.Ve
+.PP
+Aha. \f(CW\*(C`$ical\->day\*(C'\fR returned 16, but we expected 17. A
+quick check shows that the code is working fine, we made a mistake
+when writing the tests. Change it to:
+.PP
+.Vb 1
+\& is( $ical\->day, 16, \*(Aq day()\*(Aq );
+.Ve
+.PP
+\&... and everything works.
+.PP
+Any time you're doing a "this equals that" sort of test, use \f(CWis()\fR.
+It even works on arrays. The test is always in scalar context, so you
+can test how many elements are in an array this way. [5]
+.PP
+.Vb 1
+\& is( @foo, 5, \*(Aqfoo has 5 elements\*(Aq );
+.Ve
+.SS "Sometimes the tests are wrong"
+.IX Subsection "Sometimes the tests are wrong"
+This brings up a very important lesson. Code has bugs. Tests are
+code. Ergo, tests have bugs. A failing test could mean a bug in the
+code, but don't discount the possibility that the test is wrong.
+.PP
+On the flip side, don't be tempted to prematurely declare a test
+incorrect just because you're having trouble finding the bug.
+Invalidating a test isn't something to be taken lightly, and don't use
+it as a cop out to avoid work.
+.SS "Testing lots of values"
+.IX Subsection "Testing lots of values"
+We're going to be wanting to test a lot of dates here, trying to trick
+the code with lots of different edge cases. Does it work before 1970?
+After 2038? Before 1904? Do years after 10,000 give it trouble?
+Does it get leap years right? We could keep repeating the code above,
+or we could set up a little try/expect loop.
+.PP
+.Vb 2
+\& use Test::More tests => 32;
+\& use Date::ICal;
+\&
+\& my %ICal_Dates = (
+\& # An ICal string And the year, month, day
+\& # hour, minute and second we expect.
+\& \*(Aq19971024T120000\*(Aq => # from the docs.
+\& [ 1997, 10, 24, 12, 0, 0 ],
+\& \*(Aq20390123T232832\*(Aq => # after the Unix epoch
+\& [ 2039, 1, 23, 23, 28, 32 ],
+\& \*(Aq19671225T000000\*(Aq => # before the Unix epoch
+\& [ 1967, 12, 25, 0, 0, 0 ],
+\& \*(Aq18990505T232323\*(Aq => # before the MacOS epoch
+\& [ 1899, 5, 5, 23, 23, 23 ],
+\& );
+\&
+\&
+\& while( my($ical_str, $expect) = each %ICal_Dates ) {
+\& my $ical = Date::ICal\->new( ical => $ical_str );
+\&
+\& ok( defined $ical, "new(ical => \*(Aq$ical_str\*(Aq)" );
+\& ok( $ical\->isa(\*(AqDate::ICal\*(Aq), " and it\*(Aqs the right class" );
+\&
+\& is( $ical\->year, $expect\->[0], \*(Aq year()\*(Aq );
+\& is( $ical\->month, $expect\->[1], \*(Aq month()\*(Aq );
+\& is( $ical\->day, $expect\->[2], \*(Aq day()\*(Aq );
+\& is( $ical\->hour, $expect\->[3], \*(Aq hour()\*(Aq );
+\& is( $ical\->min, $expect\->[4], \*(Aq min()\*(Aq );
+\& is( $ical\->sec, $expect\->[5], \*(Aq sec()\*(Aq );
+\& }
+.Ve
+.PP
+Now we can test bunches of dates by just adding them to
+\&\f(CW%ICal_Dates\fR. Now that it's less work to test with more dates, you'll
+be inclined to just throw more in as you think of them.
+Only problem is, every time we add to that we have to keep adjusting
+the \f(CW\*(C`use Test::More tests => ##\*(C'\fR line. That can rapidly get
+annoying. There are ways to make this work better.
+.PP
+First, we can calculate the plan dynamically using the \f(CWplan()\fR
+function.
+.PP
+.Vb 2
+\& use Test::More;
+\& use Date::ICal;
+\&
+\& my %ICal_Dates = (
+\& ...same as before...
+\& );
+\&
+\& # For each key in the hash we\*(Aqre running 8 tests.
+\& plan tests => keys(%ICal_Dates) * 8;
+\&
+\& ...and then your tests...
+.Ve
+.PP
+To be even more flexible, use \f(CW\*(C`done_testing\*(C'\fR. This means we're just
+running some tests, don't know how many. [6]
+.PP
+.Vb 1
+\& use Test::More; # instead of tests => 32
+\&
+\& ... # tests here
+\&
+\& done_testing(); # reached the end safely
+.Ve
+.PP
+If you don't specify a plan, Test::More expects to see \f(CWdone_testing()\fR
+before your program exits. It will warn you if you forget it. You can give
+\&\f(CWdone_testing()\fR an optional number of tests you expected to run, and if the
+number ran differs, Test::More will give you another kind of warning.
+.SS "Informative names"
+.IX Subsection "Informative names"
+Take a look at the line:
+.PP
+.Vb 1
+\& ok( defined $ical, "new(ical => \*(Aq$ical_str\*(Aq)" );
+.Ve
+.PP
+We've added more detail about what we're testing and the ICal string
+itself we're trying out to the name. So you get results like:
+.PP
+.Vb 8
+\& ok 25 \- new(ical => \*(Aq19971024T120000\*(Aq)
+\& ok 26 \- and it\*(Aqs the right class
+\& ok 27 \- year()
+\& ok 28 \- month()
+\& ok 29 \- day()
+\& ok 30 \- hour()
+\& ok 31 \- min()
+\& ok 32 \- sec()
+.Ve
+.PP
+If something in there fails, you'll know which one it was and that
+will make tracking down the problem easier. Try to put a bit of
+debugging information into the test names.
+.PP
+Describe what the tests test, to make debugging a failed test easier
+for you or for the next person who runs your test.
+.SS "Skipping tests"
+.IX Subsection "Skipping tests"
+Poking around in the existing Date::ICal tests, I found this in
+\&\fIt/01sanity.t\fR [7]
+.PP
+.Vb 1
+\& #!/usr/bin/perl \-w
+\&
+\& use Test::More tests => 7;
+\& use Date::ICal;
+\&
+\& # Make sure epoch time is being handled sanely.
+\& my $t1 = Date::ICal\->new( epoch => 0 );
+\& is( $t1\->epoch, 0, "Epoch time of 0" );
+\&
+\& # XXX This will only work on unix systems.
+\& is( $t1\->ical, \*(Aq19700101Z\*(Aq, " epoch to ical" );
+\&
+\& is( $t1\->year, 1970, " year()" );
+\& is( $t1\->month, 1, " month()" );
+\& is( $t1\->day, 1, " day()" );
+\&
+\& # like the tests above, but starting with ical instead of epoch
+\& my $t2 = Date::ICal\->new( ical => \*(Aq19700101Z\*(Aq );
+\& is( $t2\->ical, \*(Aq19700101Z\*(Aq, "Start of epoch in ICal notation" );
+\&
+\& is( $t2\->epoch, 0, " and back to ICal" );
+.Ve
+.PP
+The beginning of the epoch is different on most non-Unix operating systems [8].
+Even though Perl smooths out the differences for the most part, certain ports
+do it differently. MacPerl is one off the top of my head. [9] Rather than
+putting a comment in the test and hoping someone will read the test while
+debugging the failure, we can explicitly say it's never going to work and skip
+the test.
+.PP
+.Vb 2
+\& use Test::More tests => 7;
+\& use Date::ICal;
+\&
+\& # Make sure epoch time is being handled sanely.
+\& my $t1 = Date::ICal\->new( epoch => 0 );
+\& is( $t1\->epoch, 0, "Epoch time of 0" );
+\&
+\& SKIP: {
+\& skip(\*(Aqepoch to ICal not working on Mac OS\*(Aq, 6)
+\& if $^O eq \*(AqMacOS\*(Aq;
+\&
+\& is( $t1\->ical, \*(Aq19700101Z\*(Aq, " epoch to ical" );
+\&
+\& is( $t1\->year, 1970, " year()" );
+\& is( $t1\->month, 1, " month()" );
+\& is( $t1\->day, 1, " day()" );
+\&
+\& # like the tests above, but starting with ical instead of epoch
+\& my $t2 = Date::ICal\->new( ical => \*(Aq19700101Z\*(Aq );
+\& is( $t2\->ical, \*(Aq19700101Z\*(Aq, "Start of epoch in ICal notation" );
+\&
+\& is( $t2\->epoch, 0, " and back to ICal" );
+\& }
+.Ve
+.PP
+A little bit of magic happens here. When running on anything but MacOS, all
+the tests run normally. But when on MacOS, \f(CWskip()\fR causes the entire
+contents of the SKIP block to be jumped over. It never runs. Instead,
+\&\f(CWskip()\fR prints special output that tells Test::Harness that the tests have
+been skipped.
+.PP
+.Vb 8
+\& 1..7
+\& ok 1 \- Epoch time of 0
+\& ok 2 # skip epoch to ICal not working on MacOS
+\& ok 3 # skip epoch to ICal not working on MacOS
+\& ok 4 # skip epoch to ICal not working on MacOS
+\& ok 5 # skip epoch to ICal not working on MacOS
+\& ok 6 # skip epoch to ICal not working on MacOS
+\& ok 7 # skip epoch to ICal not working on MacOS
+.Ve
+.PP
+This means your tests won't fail on MacOS. This means fewer emails
+from MacPerl users telling you about failing tests that you know will
+never work. You've got to be careful with skip tests. These are for
+tests which don't work and \fInever will\fR. It is not for skipping
+genuine bugs (we'll get to that in a moment).
+.PP
+The tests are wholly and completely skipped. [10] This will work.
+.PP
+.Vb 2
+\& SKIP: {
+\& skip("I don\*(Aqt wanna die!");
+\&
+\& die, die, die, die, die;
+\& }
+.Ve
+.SS "Todo tests"
+.IX Subsection "Todo tests"
+While thumbing through the Date::ICal man page, I came across this:
+.PP
+.Vb 1
+\& ical
+\&
+\& $ical_string = $ical\->ical;
+\&
+\& Retrieves, or sets, the date on the object, using any
+\& valid ICal date/time string.
+.Ve
+.PP
+"Retrieves or sets". Hmmm. I didn't see a test for using \f(CWical()\fR to set
+the date in the Date::ICal test suite. So I wrote one:
+.PP
+.Vb 2
+\& use Test::More tests => 1;
+\& use Date::ICal;
+\&
+\& my $ical = Date::ICal\->new;
+\& $ical\->ical(\*(Aq20201231Z\*(Aq);
+\& is( $ical\->ical, \*(Aq20201231Z\*(Aq, \*(AqSetting via ical()\*(Aq );
+.Ve
+.PP
+Run that. I saw:
+.PP
+.Vb 6
+\& 1..1
+\& not ok 1 \- Setting via ical()
+\& # Failed test (\- at line 6)
+\& # got: \*(Aq20010814T233649Z\*(Aq
+\& # expected: \*(Aq20201231Z\*(Aq
+\& # Looks like you failed 1 tests of 1.
+.Ve
+.PP
+Whoops! Looks like it's unimplemented. Assume you don't have the time to fix
+this. [11] Normally, you'd just comment out the test and put a note in a todo
+list somewhere. Instead, explicitly state "this test will fail" by wrapping it
+in a \f(CW\*(C`TODO\*(C'\fR block:
+.PP
+.Vb 1
+\& use Test::More tests => 1;
+\&
+\& TODO: {
+\& local $TODO = \*(Aqical($ical) not yet implemented\*(Aq;
+\&
+\& my $ical = Date::ICal\->new;
+\& $ical\->ical(\*(Aq20201231Z\*(Aq);
+\&
+\& is( $ical\->ical, \*(Aq20201231Z\*(Aq, \*(AqSetting via ical()\*(Aq );
+\& }
+.Ve
+.PP
+Now when you run, it's a little different:
+.PP
+.Vb 4
+\& 1..1
+\& not ok 1 \- Setting via ical() # TODO ical($ical) not yet implemented
+\& # got: \*(Aq20010822T201551Z\*(Aq
+\& # expected: \*(Aq20201231Z\*(Aq
+.Ve
+.PP
+Test::More doesn't say "Looks like you failed 1 tests of 1". That '#
+TODO' tells Test::Harness "this is supposed to fail" and it treats a
+failure as a successful test. You can write tests even before
+you've fixed the underlying code.
+.PP
+If a TODO test passes, Test::Harness will report it "UNEXPECTEDLY
+SUCCEEDED". When that happens, remove the TODO block with \f(CW\*(C`local $TODO\*(C'\fR and
+turn it into a real test.
+.SS "Testing with taint mode."
+.IX Subsection "Testing with taint mode."
+Taint mode is a funny thing. It's the globalest of all global
+features. Once you turn it on, it affects \fIall\fR code in your program
+and \fIall\fR modules used (and all the modules they use). If a single
+piece of code isn't taint clean, the whole thing explodes. With that
+in mind, it's very important to ensure your module works under taint
+mode.
+.PP
+It's very simple to have your tests run under taint mode. Just throw
+a \f(CW\*(C`\-T\*(C'\fR into the \f(CW\*(C`#!\*(C'\fR line. Test::Harness will read the switches
+in \f(CW\*(C`#!\*(C'\fR and use them to run your tests.
+.PP
+.Vb 1
+\& #!/usr/bin/perl \-Tw
+\&
+\& ...test normally here...
+.Ve
+.PP
+When you say \f(CW\*(C`make test\*(C'\fR it will run with taint mode on.
+.SH FOOTNOTES
+.IX Header "FOOTNOTES"
+.IP 1. 4
+The first number doesn't really mean anything, but it has to be 1.
+It's the second number that's important.
+.IP 2. 4
+For those following along at home, I'm using version 1.31. It has
+some bugs, which is good \-\- we'll uncover them with our tests.
+.IP 3. 4
+You can actually take this one step further and test the manual
+itself. Have a look at Test::Inline (formerly Pod::Tests).
+.IP 4. 4
+Yes, there's a mistake in the test suite. What! Me, contrived?
+.IP 5. 4
+We'll get to testing the contents of lists later.
+.IP 6. 4
+But what happens if your test program dies halfway through?! Since we
+didn't say how many tests we're going to run, how can we know it
+failed? No problem, Test::More employs some magic to catch that death
+and turn the test into a failure, even if every test passed up to that
+point.
+.IP 7. 4
+I cleaned it up a little.
+.IP 8. 4
+Most Operating Systems record time as the number of seconds since a
+certain date. This date is the beginning of the epoch. Unix's starts
+at midnight January 1st, 1970 GMT.
+.IP 9. 4
+MacOS's epoch is midnight January 1st, 1904. VMS's is midnight,
+November 17th, 1858, but vmsperl emulates the Unix epoch so it's not a
+problem.
+.IP 10. 4
+As long as the code inside the SKIP block at least compiles. Please
+don't ask how. No, it's not a filter.
+.IP 11. 4
+Do NOT be tempted to use TODO tests as a way to avoid fixing simple
+bugs!
+.SH AUTHORS
+.IX Header "AUTHORS"
+Michael G Schwern <schwern@pobox.com> and the perl-qa dancers!
+.SH MAINTAINERS
+.IX Header "MAINTAINERS"
+.IP "Chad Granum <exodist@cpan.org>" 4
+.IX Item "Chad Granum <exodist@cpan.org>"
+.SH COPYRIGHT
+.IX Header "COPYRIGHT"
+Copyright 2001 by Michael G Schwern <schwern@pobox.com>.
+.PP
+This documentation is free; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+.PP
+Irrespective of its distribution, all code examples in these files
+are hereby placed into the public domain. You are permitted and
+encouraged to use this code in your own programs for fun
+or for profit as you see fit. A simple comment in the code giving
+credit would be courteous but is not required.