X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FGitalist.git;a=blobdiff_plain;f=local-lib5%2Fman%2Fman3%2FTest%3A%3ATutorial.3pm;fp=local-lib5%2Fman%2Fman3%2FTest%3A%3ATutorial.3pm;h=38f0caed8fdb5936f3d76ba8ad06a2ebcc7b9216;hp=0000000000000000000000000000000000000000;hb=3fea05b9fbf95091f4522528b9980a33e0235603;hpb=af746827daa7a8feccee889e1d12ebc74cc9201e diff --git a/local-lib5/man/man3/Test::Tutorial.3pm b/local-lib5/man/man3/Test::Tutorial.3pm new file mode 100644 index 0000000..38f0cae --- /dev/null +++ b/local-lib5/man/man3/Test::Tutorial.3pm @@ -0,0 +1,841 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.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 +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "Test::Tutorial 3" +.TH Test::Tutorial 3 "2009-09-02" "perl v5.8.7" "User Contributed Perl Documentation" +.SH "NAME" +Test::Tutorial \- A tutorial about writing really basic tests +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fI\s-1AHHHHHHH\s0!!!! \s-1NOT\s0 \s-1TESTING\s0! 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... +.Sh "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 +.Ve +.PP +.Vb 1 +\& print "1..1\en"; +.Ve +.PP +.Vb 1 +\& print 1 + 1 == 2 ? "ok 1\en" : "not ok 1\en"; +.Ve +.PP +since 1 + 1 is 2, it prints: +.PP +.Vb 2 +\& 1..1 +\& ok 1 +.Ve +.PP +What this says is: \f(CW1..1\fR \*(L"I'm going to run one test.\*(R" [1] \f(CW\*(C`ok 1\*(C'\fR +\&\*(L"The first test passed\*(R". 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. \fBTest::Harness\fR 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 \fBTest::Simple\fR. It has one function, \f(CW\*(C`ok()\*(C'\fR. +.PP +.Vb 1 +\& #!/usr/bin/perl \-w +.Ve +.PP +.Vb 1 +\& use Test::Simple tests => 1; +.Ve +.PP +.Vb 1 +\& ok( 1 + 1 == 2 ); +.Ve +.PP +and that does the same thing as the code above. \f(CW\*(C`ok()\*(C'\fR is the backbone +of Perl testing, and we'll be using it instead of roll-your-own from +here on. If \f(CW\*(C`ok()\*(C'\fR gets a true value, the test passes. False, it +fails. +.PP +.Vb 1 +\& #!/usr/bin/perl \-w +.Ve +.PP +.Vb 3 +\& 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 \*(L"I'm going to run two tests.\*(R" This number is used 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 \*(L"The first test passed.\*(R" \f(CW\*(C`not ok 2\*(C'\fR \*(L"The second test +failed\*(R". 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, \fBDate::ICal\fR. It's on \s-1CPAN\s0, so download a copy and follow +along. [2] +.Sh "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. Best place to start is at the beginning. Date::ICal is +an object-oriented module, and that means you start by making an +object. So we test \f(CW\*(C`new()\*(C'\fR. +.PP +.Vb 1 +\& #!/usr/bin/perl \-w +.Ve +.PP +.Vb 1 +\& use Test::Simple tests => 2; +.Ve +.PP +.Vb 1 +\& use Date::ICal; +.Ve +.PP +.Vb 3 +\& my $ical = Date::ICal\->new; # create an object +\& ok( defined $ical ); # check that we got something +\& ok( $ical\->isa('Date::ICal') ); # and it's 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. +.Sh "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? +.PP +Each test can be given a little descriptive name as the second +argument to \f(CW\*(C`ok()\*(C'\fR. +.PP +.Vb 1 +\& use Test::Simple tests => 2; +.Ve +.PP +.Vb 2 +\& ok( defined $ical, 'new() returned something' ); +\& ok( $ical\->isa('Date::ICal'), " and it's the right class" ); +.Ve +.PP +So now you'd see... +.PP +.Vb 3 +\& 1..2 +\& ok 1 \- new() returned something +\& ok 2 \- and it's the right class +.Ve +.Sh "Test the manual" +.IX Subsection "Test the manual" +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 +\&\*(L"\s-1SYNOPSIS\s0\*(R" in Date::ICal and test that all its bits work. +.PP +.Vb 1 +\& #!/usr/bin/perl \-w +.Ve +.PP +.Vb 1 +\& use Test::Simple tests => 8; +.Ve +.PP +.Vb 1 +\& use Date::ICal; +.Ve +.PP +.Vb 3 +\& $ical = Date::ICal\->new( year => 1964, month => 10, day => 16, +\& hour => 16, min => 12, sec => 47, +\& tz => '0530' ); +.Ve +.PP +.Vb 8 +\& ok( defined $ical, 'new() returned something' ); +\& ok( $ical\->isa('Date::ICal'), " and it's the right class" ); +\& ok( $ical\->sec == 47, ' sec()' ); +\& ok( $ical\->min == 12, ' min()' ); +\& ok( $ical\->hour == 16, ' hour()' ); +\& ok( $ical\->day == 17, ' day()' ); +\& ok( $ical\->month == 10, ' month()' ); +\& ok( $ical\->year == 1964, ' year()' ); +.Ve +.PP +run that and you get: +.PP +.Vb 11 +\& 1..8 +\& ok 1 \- new() returned something +\& ok 2 \- and it's 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. We'll have to re-run the +test in the debugger or throw in some print statements to find out. +.PP +Instead, we'll switch from \fBTest::Simple\fR to \fBTest::More\fR. \fBTest::More\fR +does everything \fBTest::Simple\fR 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 \*(L"ok\*(R". +Although you can write almost any test with a generic \f(CW\*(C`ok()\*(C'\fR, it +can't tell you what went wrong. Instead, we'll use the \f(CW\*(C`is()\*(C'\fR +function, which lets us declare that something is supposed to be the +same as something else: +.PP +.Vb 1 +\& #!/usr/bin/perl \-w +.Ve +.PP +.Vb 1 +\& use Test::More tests => 8; +.Ve +.PP +.Vb 1 +\& use Date::ICal; +.Ve +.PP +.Vb 3 +\& $ical = Date::ICal\->new( year => 1964, month => 10, day => 16, +\& hour => 16, min => 12, sec => 47, +\& tz => '0530' ); +.Ve +.PP +.Vb 8 +\& ok( defined $ical, 'new() returned something' ); +\& ok( $ical\->isa('Date::ICal'), " and it's the right class" ); +\& is( $ical\->sec, 47, ' sec()' ); +\& is( $ical\->min, 12, ' min()' ); +\& is( $ical\->hour, 16, ' hour()' ); +\& is( $ical\->day, 17, ' day()' ); +\& is( $ical\->month, 10, ' month()' ); +\& is( $ical\->year, 1964, ' year()' ); +.Ve +.PP +"Is \f(CW\*(C`$ical\->sec\*(C'\fR 47?\*(L" \*(R"Is \f(CW\*(C`$ical\->min\*(C'\fR 12?" With \f(CW\*(C`is()\*(C'\fR in place, +you get some more information +.PP +.Vb 13 +\& 1..8 +\& ok 1 \- new() returned something +\& ok 2 \- and it's the right class +\& ok 3 \- sec() +\& ok 4 \- min() +\& ok 5 \- hour() +\& not ok 6 \- day() +\& # Failed test (\- at line 16) +\& # got: '16' +\& # expected: '17' +\& ok 7 \- month() +\& ok 8 \- year() +\& # Looks like you failed 1 tests of 8. +.Ve +.PP +letting us know that \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 up the tests. Just change it to: +.PP +.Vb 1 +\& is( $ical\->day, 16, ' day()' ); +.Ve +.PP +and everything works. +.PP +So any time you're doing a \*(L"this equals that\*(R" sort of test, use \f(CW\*(C`is()\*(C'\fR. +It even works on arrays. The test is always in scalar context, so you +can test how many elements are in a list this way. [5] +.PP +.Vb 1 +\& is( @foo, 5, 'foo has 5 elements' ); +.Ve +.Sh "Sometimes the tests are wrong" +.IX Subsection "Sometimes the tests are wrong" +Which brings us to 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. +.Sh "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; +.Ve +.PP +.Vb 12 +\& my %ICal_Dates = ( +\& # An ICal string And the year, month, day +\& # hour, minute and second we expect. +\& '19971024T120000' => # from the docs. +\& [ 1997, 10, 24, 12, 0, 0 ], +\& '20390123T232832' => # after the Unix epoch +\& [ 2039, 1, 23, 23, 28, 32 ], +\& '19671225T000000' => # before the Unix epoch +\& [ 1967, 12, 25, 0, 0, 0 ], +\& '18990505T232323' => # before the MacOS epoch +\& [ 1899, 5, 5, 23, 23, 23 ], +\& ); +.Ve +.PP +.Vb 2 +\& while( my($ical_str, $expect) = each %ICal_Dates ) { +\& my $ical = Date::ICal\->new( ical => $ical_str ); +.Ve +.PP +.Vb 2 +\& ok( defined $ical, "new(ical => '$ical_str')" ); +\& ok( $ical\->isa('Date::ICal'), " and it's the right class" ); +.Ve +.PP +.Vb 7 +\& is( $ical\->year, $expect\->[0], ' year()' ); +\& is( $ical\->month, $expect\->[1], ' month()' ); +\& is( $ical\->day, $expect\->[2], ' day()' ); +\& is( $ical\->hour, $expect\->[3], ' hour()' ); +\& is( $ical\->min, $expect\->[4], ' min()' ); +\& is( $ical\->sec, $expect\->[5], ' sec()' ); +\& } +.Ve +.PP +So 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's two ways to make this work better. +.PP +First, we can calculate the plan dynamically using the \f(CW\*(C`plan()\*(C'\fR +function. +.PP +.Vb 2 +\& use Test::More; +\& use Date::ICal; +.Ve +.PP +.Vb 3 +\& my %ICal_Dates = ( +\& ...same as before... +\& ); +.Ve +.PP +.Vb 2 +\& # For each key in the hash we're running 8 tests. +\& plan tests => keys(%ICal_Dates) * 8; +.Ve +.PP +.Vb 1 +\& ...and then your tests... +.Ve +.PP +Or to be even more flexible, we use \f(CW\*(C`no_plan\*(C'\fR. This means we're just +running some tests, don't know how many. [6] +.PP +.Vb 1 +\& use Test::More 'no_plan'; # instead of tests => 32 +.Ve +.PP +now we can just add tests and not have to do all sorts of math to +figure out how many we're running. +.Sh "Informative names" +.IX Subsection "Informative names" +Take a look at this line here +.PP +.Vb 1 +\& ok( defined $ical, "new(ical => '$ical_str')" ); +.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 => '19971024T120000') +\& ok 26 \- and it's 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. So 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. +.Sh "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 +.Ve +.PP +.Vb 2 +\& use Test::More tests => 7; +\& use Date::ICal; +.Ve +.PP +.Vb 3 +\& # Make sure epoch time is being handled sanely. +\& my $t1 = Date::ICal\->new( epoch => 0 ); +\& is( $t1\->epoch, 0, "Epoch time of 0" ); +.Ve +.PP +.Vb 2 +\& # XXX This will only work on unix systems. +\& is( $t1\->ical, '19700101Z', " epoch to ical" ); +.Ve +.PP +.Vb 3 +\& is( $t1\->year, 1970, " year()" ); +\& is( $t1\->month, 1, " month()" ); +\& is( $t1\->day, 1, " day()" ); +.Ve +.PP +.Vb 3 +\& # like the tests above, but starting with ical instead of epoch +\& my $t2 = Date::ICal\->new( ical => '19700101Z' ); +\& is( $t2\->ical, '19700101Z', "Start of epoch in ICal notation" ); +.Ve +.PP +.Vb 1 +\& 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] So rather than just putting a comment in the test, +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; +.Ve +.PP +.Vb 3 +\& # Make sure epoch time is being handled sanely. +\& my $t1 = Date::ICal\->new( epoch => 0 ); +\& is( $t1\->epoch, 0, "Epoch time of 0" ); +.Ve +.PP +.Vb 3 +\& SKIP: { +\& skip('epoch to ICal not working on MacOS', 6) +\& if $^O eq 'MacOS'; +.Ve +.PP +.Vb 1 +\& is( $t1\->ical, '19700101Z', " epoch to ical" ); +.Ve +.PP +.Vb 3 +\& is( $t1\->year, 1970, " year()" ); +\& is( $t1\->month, 1, " month()" ); +\& is( $t1\->day, 1, " day()" ); +.Ve +.PP +.Vb 3 +\& # like the tests above, but starting with ical instead of epoch +\& my $t2 = Date::ICal\->new( ical => '19700101Z' ); +\& is( $t2\->ical, '19700101Z', "Start of epoch in ICal notation" ); +.Ve +.PP +.Vb 2 +\& 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(CW\*(C`skip()\*(C'\fR causes +the entire contents of the \s-1SKIP\s0 block to be jumped over. It's never +run. Instead, it 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 less 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't wanna die!"); +.Ve +.PP +.Vb 2 +\& die, die, die, die, die; +\& } +.Ve +.Sh "Todo tests" +.IX Subsection "Todo tests" +Thumbing through the Date::ICal man page, I came across this: +.PP +.Vb 1 +\& ical +.Ve +.PP +.Vb 1 +\& $ical_string = $ical\->ical; +.Ve +.PP +.Vb 2 +\& Retrieves, or sets, the date on the object, using any +\& valid ICal date/time string. +.Ve +.PP +\&\*(L"Retrieves or sets\*(R". Hmmm, didn't see a test for using \f(CW\*(C`ical()\*(C'\fR to set +the date in the Date::ICal test suite. So I'll write one. +.PP +.Vb 2 +\& use Test::More tests => 1; +\& use Date::ICal; +.Ve +.PP +.Vb 3 +\& my $ical = Date::ICal\->new; +\& $ical\->ical('20201231Z'); +\& is( $ical\->ical, '20201231Z', 'Setting via ical()' ); +.Ve +.PP +run that and I get +.PP +.Vb 6 +\& 1..1 +\& not ok 1 \- Setting via ical() +\& # Failed test (\- at line 6) +\& # got: '20010814T233649Z' +\& # expected: '20201231Z' +\& # Looks like you failed 1 tests of 1. +.Ve +.PP +Whoops! Looks like it's unimplemented. Let's assume we 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, we're going to +explicitly state \*(L"this test will fail\*(R" by wrapping it in a \f(CW\*(C`TODO\*(C'\fR block. +.PP +.Vb 1 +\& use Test::More tests => 1; +.Ve +.PP +.Vb 2 +\& TODO: { +\& local $TODO = 'ical($ical) not yet implemented'; +.Ve +.PP +.Vb 2 +\& my $ical = Date::ICal\->new; +\& $ical\->ical('20201231Z'); +.Ve +.PP +.Vb 2 +\& is( $ical\->ical, '20201231Z', 'Setting via ical()' ); +\& } +.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: '20010822T201551Z' +\& # expected: '20201231Z' +.Ve +.PP +Test::More doesn't say \*(L"Looks like you failed 1 tests of 1\*(R". That '# +\&\s-1TODO\s0' tells Test::Harness \*(L"this is supposed to fail\*(R" and it treats a +failure as a successful test. So you can write tests even before +you've fixed the underlying code. +.PP +If a \s-1TODO\s0 test passes, Test::Harness will report it \*(L"\s-1UNEXPECTEDLY\s0 +\&\s-1SUCCEEDED\s0\*(R". When that happens, you simply remove the \s-1TODO\s0 block with +\&\f(CW\*(C`local $TODO\*(C'\fR and turn it into a real test. +.Sh "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 +.Ve +.PP +.Vb 1 +\& ...test normally here... +.Ve +.PP +So when you say \f(CW\*(C`make test\*(C'\fR it will be run with taint mode and +warnings on. +.SH "FOOTNOTES" +.IX Header "FOOTNOTES" +.IP "1" 4 +.IX Item "1" +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 +.IX Item "2" +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 +.IX Item "3" +You can actually take this one step further and test the manual +itself. Have a look at \fBTest::Inline\fR (formerly \fBPod::Tests\fR). +.IP "4" 4 +.IX Item "4" +Yes, there's a mistake in the test suite. What! Me, contrived? +.IP "5" 4 +.IX Item "5" +We'll get to testing the contents of lists later. +.IP "6" 4 +.IX Item "6" +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 +.IX Item "7" +I cleaned it up a little. +.IP "8" 4 +.IX Item "8" +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 \s-1GMT\s0. +.IP "9" 4 +.IX Item "9" +MacOS's epoch is midnight January 1st, 1904. \s-1VMS\s0's is midnight, +November 17th, 1858, but vmsperl emulates the Unix epoch so it's not a +problem. +.IP "10" 4 +.IX Item "10" +As long as the code inside the \s-1SKIP\s0 block at least compiles. Please +don't ask how. No, it's not a filter. +.IP "11" 4 +.IX Item "11" +Do \s-1NOT\s0 be tempted to use \s-1TODO\s0 tests as a way to avoid fixing simple +bugs! +.SH "AUTHORS" +.IX Header "AUTHORS" +Michael G Schwern and the perl-qa dancers! +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +Copyright 2001 by Michael G Schwern . +.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.