.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) .\" .\" 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 .. .\" 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. \*(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- .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\} .\" .\" 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 turned on, 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. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" 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::Routine::Manual::Demo 3pm" .TH Test::Routine::Manual::Demo 3pm "2012-03-16" "perl v5.14.2" "User Contributed Perl Documentation" .\" 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::Routine::Manual::Demo \- a walkthrough, in code, of Test::Routine .SH "VERSION" .IX Header "VERSION" version 0.015 .SH "The Demo" .IX Header "The Demo" .SS "t/demo/01\-demo.t" .IX Subsection "t/demo/01-demo.t" .Vb 3 \& #!/bin/env perl \& use strict; \& use warnings; \& \& # This test is both a test and an example of how Test::Routine works! Welcome \& # to t/01\-demo.t, I will be your guide, rjbs. \& \& { \& # This block defines the HashTester package. It\*(Aqs a Test::Routine, meaning \& # it\*(Aqs a role. We define state that the test will need to keep and any \& # requirements we might have. \& # \& # Before we can run this test, we\*(Aqll need to compose the role into a class so \& # that we can make an instance. \& package HashTester; \& use Test::Routine; \& \& # We import stuff from Test::More because, well, who wants to re\-write all \& # those really useful test routines that exist out there? Maybe somebody, \& # but not me. \& use Test::More; \& \& # ...but then we use namespace::autoclean to get rid of the routines once \& # we\*(Aqve bound to them. This is just standard Moose practice, anyway, right? \& use namespace::autoclean; \& \& # Finally, some state! Every test will get called as method on an instance, \& # and it will have this attribute. Here are some points of interest: \& # \& # \- We\*(Aqre giving this attribute a builder, so it will try to get built with a \& # call to $self\->build_hash_to_test \-\- so each class that composes this \& # role can provide means for these attributes (fixtures) to be generated as \& # needed. \& # \& # \- We are not adding "requires \*(Aqbuild_hash_to_test\*(Aq", because then we can \& # apply this role to Moose::Object and instantiate it with a given value \& # in the constructor. There will be an example of this below. This lets \& # us re\-use these tests in many variations without having to write class \& # after class. \& # \& # \- We don\*(Aqt use lazy_build because it would create a clearer. If someone \& # then cleared our lazy_build fixture, it could not be re\-built in the \& # event that we\*(Aqd gotten it explicitly from the constructor! \& # \& # Using Moose attributes for our state and fixtures allows us to get all of \& # their powerful behaviors like types, delegation, traits, and so on, and \& # allows us to decompose shared behavior into roles. \& # \& has hash_to_test => ( \& is => \*(Aqro\*(Aq, \& isa => \*(AqHashRef\*(Aq, \& builder => \*(Aqbuild_hash_to_test\*(Aq, \& ); \& \& # Here, we\*(Aqre just declaring an actual test that we will run. This sub will \& # get installed as a method with a name that won\*(Aqt get clobbered easily. The \& # method will be found later by run_tests so we can find and execute all \& # tests on an instance. \& # \& # There is nothing magical about this method! Calling this method is \& # performed in a Test::More subtest block. A TAP plan can be issued with \& # "plan", and we can issue TODO or SKIP directives the same way. There is \& # none of the return\-to\-skip magic that we find in Test::Class. \& # \& # The string after "test" is used as the method name \-\- which means we\*(Aqre \& # getting a method name with spaces in it. This can be slightly problematic \& # if you try to use, say, ::, in a method name. For the most part, it works \& # quite well \-\- but look at the next test for an example of how to give an \& # explicit description. \& test "only one key in hash" => sub { \& my ($self) = @_; \& \& my $hash = $self\->hash_to_test; \& \& is(keys %$hash, 1, "we have one key in our test hash"); \& is(2+2, 4, "universe still okay"); \& }; \& \& # The only thing of note here is that we\*(Aqre passing a hashref of extra args \& # to the test method constructor. "desc" lets us set the test\*(Aqs description, \& # which is used in the test output, so we can avoid weird method names being \& # installed. Also note that we order tests more or less by order of \& # definition, not by name or description. \& test second_test => { desc => "Test::Routine demo!" } => sub { \& pass("We\*(Aqre running this test second"); \& pass("...notice that the subtest\*(Aqs label is the \*(Aqdesc\*(Aq above"); \& pass("...and not the method name!"); \& }; \& } \& \& { \& # This package is one fixture against which we can run the HashTester \& # routine. It has the only thing it needs: a build_hash_to_test method. \& # Obviously real examples would have more to them than this. \& package ProcessHash; \& use Moose; \& with \*(AqHashTester\*(Aq; \& \& use namespace::autoclean; \& \& sub build_hash_to_test { return { $$ => $^T } } \& } \& \& # Now we\*(Aqre into the body of the test program: where tests actually get run. \& \& # We use Test::Routine::Util to get its "run_tests" routine, which runs the \& # tests on an instance, building it if needed. \& use Test::Routine::Util; \& \& # We use Test::More to get done_testing. We don\*(Aqt assume that run_tests is the \& # entire test, because that way we can (as we do here) run multiple test \& # instances, and can intersperse other kinds of sanity checks amongst the \& # Test::Routine\-style tests. \& use Test::More; \& \& is(2+2, 4, "universe still makes sense") or BAIL_OUT("PANIC!"); \& \& # The first arg is a description for the subtest that will be run. The second, \& # here, is a class that will be instantiated and tested. \& run_tests(\*(AqProcessHash class\*(Aq => \*(AqProcessHash\*(Aq); \& \& # Here, the second argument is an instance of a class to test. \& run_tests(\*(AqProcessHash obj\*(Aq => ProcessHash\->new({ hash_to_test => { 1 => 0 }})); \& \& # We could also just supply a class name and a set of args to pass to new. \& # The below is very nearly equivalent to the above: \& run_tests(\*(AqProcessHash new\*(Aq => ProcessHash => { hash_to_test => { 1 => 0 }}); \& \& # ...and here, the second arg is not a class or instance at all, but the \& # Test::Routine role (by name). Since we know we can\*(Aqt instantiate a role, \& # run_tests will try to compose it with Moose::Object. Then the args are used \& # as the args to \->new on the new class, as above. This lets us write \& # Test::Routines that can be tested with the right state to start with, or \& # Test::Routines that need to be composed with testing fixture classes. \& run_tests( \& \*(AqHashTester with given state\*(Aq, \& HashTester => { \& hash_to_test => { a => 1 }, \& }, \& ); \& \& # There\*(Aqs one more interesting way to run out tests, but it\*(Aqs demonstrated in \& # 02\-simple.t instead of here. Go check that out. \& \& # ...and we\*(Aqre done! \& done_testing; .Ve .SS "t/demo/02\-simple.t" .IX Subsection "t/demo/02-simple.t" .Vb 8 \& # Welcome to part two of the Test::Routine demo. This is showing how you can \& # write quick one\-off tests without having to write a bunch of .pm files or \& # (worse?) embed packages in bare blocks in the odious way that 01\-demo.t did. \& # \& # First off, we use Test::Routine. As it did before, this turns the current \& # package (main!) into a Test::Routine role. It also has the pleasant \& # side\-effect of turning on strict and warnings. \& use Test::Routine; \& \& # Then we bring in the utils, because we\*(Aqll want to run_tests later. \& use Test::Routine::Util; \& \& # And, finally, we bring in Test::More so that we can use test assertions, and \& # namespace::autoclean to clean up after us. \& use Test::More; \& use namespace::autoclean; \& \& # We\*(Aqre going to give our tests some state. It\*(Aqs nothing special. \& has counter => ( \& is => \*(Aqrw\*(Aq, \& isa => \*(AqInt\*(Aq, \& default => 0, \& ); \& \& # Then another boring but useful hunk of code: a method for our test routine. \& sub counter_is_even { \& my ($self) = @_; \& return $self\->counter % 2 == 0; \& } \& \& # Then we can write some tests, just like we did before. Here, we\*(Aqre writing \& # several tests, and they will be run in the order in which they were defined. \& # You can see that they rely on the state being maintained. \& test \*(Aqstart even\*(Aq => sub { \& my ($self) = @_; \& ok($self\->counter_is_even, "we start with an even counter"); \& \& $self\->counter( $self\->counter + 1); \& }; \& \& test \*(Aqterminate odd\*(Aq => sub { \& my ($self) = @_; \& \& ok(! $self\->counter_is_even, "the counter is odd, so state was preserved"); \& pass("for your information, the counter is " . $self\->counter); \& }; \& \& # Now we can run these tests just by saying "run_me" \-\- rather than expecting a \& # class or role name, it uses the caller. In this case, the calling package \& # (main!) is a Test::Routine, so the runner composes it with Moose::Object, \& # instantiating it, and running the tests on the instance. \& run_me; \& \& # Since each test run gets its own instance, we can run the test suite again, \& # possibly to verify that the test suite is not destructive of some external \& # state. \& run_me("second run"); \& \& # And we can pass in args to use when constructing the object to be tested. \& # Given the tests above, we can pick any starting value for "counter" that is \& # even. \& run_me({ counter => 192 }); \& \& # ...and we\*(Aqre done! \& done_testing; \& \& # More Test::Routine behavior is demonstrated in t/03\-advice.t and t/04\-misc.t \& # Go have a look at those! .Ve .SS "t/demo/03\-advice.t" .IX Subsection "t/demo/03-advice.t" .Vb 3 \& use Test::Routine; \& use Test::Routine::Util; \& use Test::More; \& \& use namespace::autoclean; \& \& # xUnit style testing has the idea of setup and teardown that happens around \& # each test. With Test::Routine, we assume that you will do most of this sort \& # of thing in your BUILD, DEMOLISH, and attribute management. Still, you can \& # easily do setup and teardown by applying method modifiers to the "run_test" \& # method, which your Test::Routine uses to run each test. Here\*(Aqs a simple \& # example. \& \& # We have the same boring state that we saw before. It\*(Aqs just an integer that \& # is carried over between tests. \& has counter => ( \& is => \*(Aqrw\*(Aq, \& isa => \*(AqInt\*(Aq, \& lazy => 1, \& default => 0, \& clearer => \*(Aqclear_counter\*(Aq, \& ); \& \& # The first test changes the counter\*(Aqs value and leaves it changed. \& test test_0 => sub { \& my ($self) = @_; \& \& is($self\->counter, 0, \*(Aqstart with counter = 0\*(Aq); \& $self\->counter( $self\->counter + 1); \& is($self\->counter, 1, \*(Aqend with counter = 1\*(Aq); \& }; \& \& # The second test assumes that the value is the default, again. We want to \& # make sure that before each test, the counter is reset, but we don\*(Aqt want to \& # tear down and recreate the whole object, because it may have other, more \& # expensive resources built. \& test test_1 => sub { \& my ($self) = @_; \& \& is($self\->counter, 0, \*(Aqcounter is reset between tests\*(Aq); \& }; \& \& # ...so we apply a "before" modifier to each test run, calling the clearer on \& # the counter. When next accessed, it will re\-initialize to zero. We could \& # call any other code we want here, and we can compose numerous modifiers \& # together onto run_test. \& # \& # If you want to clear *all* the object state between each test... you probably \& # want to refactor. \& before run_test => sub { $_[0]\->clear_counter }; \& \& run_me; \& done_testing; .Ve .SS "t/demo/04\-misc.t" .IX Subsection "t/demo/04-misc.t" .Vb 3 \& use Test::Routine; \& use Test::Routine::Util; \& use Test::More; \& \& use namespace::autoclean; \& \& # One thing that the previous examples didn\*(Aqt show was how to mark tests as \& # "skipped" or "todo." Test::Routine makes \-no\- provisions for these \& # directives. Instead, it assumes you will use the entirely usable mechanisms \& # provided by Test::More. \& \& # This is a normal test. It is neither skipped nor todo. \& test boring_ordinary_tests => sub { \& pass("This is a plain old boring test that always passes."); \& pass("It\*(Aqs here just to remind you what they look like."); \& }; \& \& # To skip a test, we just add a "skip_all" plan. Because test methods get run \& # in subtests, this skips the whole subtest, but nothing else. \& test sample_skip_test => sub { \& plan skip_all => "these tests don\*(Aqt pass, for some reason"; \& \& is(6, 9, "I don\*(Aqt mind."); \& }; \& \& # To mark a test todo, we just set our local $TODO variable. Because the test \& # is its own block, this works just like it would in any other Test::More test. \& test sample_todo_test => sub { \& local $TODO = \*(Aqdemo of todo\*(Aq; \& \& is(2 + 2, 5, "we can bend the fabric of reality"); \& }; \& \& run_me; \& done_testing; .Ve .SS "t/demo/05\-multiple.t" .IX Subsection "t/demo/05-multiple.t" .Vb 3 \& #!/bin/env perl \& use strict; \& use warnings; \& \& use Test::Routine::Util; \& use Test::More; \& \& # One of the benefits of building our sets of tests into roles instead of \& # classes is that we can re\-use them in whatever combination we want. We can \& # break down sets of tests into bits that can be re\-used in different cases. \& # With classes, this would lead to multiple inheritance or other monstrosities. \& \& # Here\*(Aqs a first Test::Routine. We use it to make sure that one of our \& # fixture\*(Aqs attributes is a numeric id. \& { \& package Test::ThingHasID; \& use Test::Routine; \& use Test::More; \& \& requires \*(Aqid\*(Aq; \& \& test thing_has_numeric_id => sub { \& my ($self) = @_; \& \& my $id = $self\->id; \& like($id, qr/\eA[0\-9]+\ez/, "the thing\*(Aqs id is a string of ascii digits"); \& }; \& } \& \& # A second one ensures that the thing has an associated directory that \& # looks like a unix path. \& { \& package Test::HasDirectory; \& use Test::Routine; \& use Test::More; \& \& requires \*(Aqdir\*(Aq; \& \& test thing_has_unix_dir => sub { \& my ($self) = @_; \& \& my $dir = $self\->dir; \& like($dir, qr{\eA(?:/\ew+)+/?\ez}, "thing has a unix\-like directory"); \& }; \& } \& \& # We might have one class that is only expected to pass one test: \& { \& package JustHasID; \& use Moose; \& \& has id => ( \& is => \*(Aqro\*(Aq, \& default => sub { \& my ($self) = @_; \& return Scalar::Util::refaddr($self); \& }, \& ); \& } \& \& # ...and another class that should pass both: \& { \& package UnixUser; \& use Moose; \& \& has id => (is => \*(Aqro\*(Aq, default => 501); \& has dir => (is => \*(Aqro\*(Aq, default => \*(Aq/home/users/rjbs\*(Aq); \& } \& \& # So far, none of this is new, it\*(Aqs just a slightly different way of factoring \& # things we\*(Aqve seen before. In t/01\-demo.t, we wrote distinct test roles and \& # classes, and we made our class compose the role explicitly. This can be \& # a useful way to put these pieces together, but we also might want to write \& # all these classes and roles as unconnected components and compose them only \& # when we\*(Aqre ready to run our tests. When we do that, we can tell run_tests \& # what to put together. \& # \& # Here, we tell it that we can test JustHasID with Test::ThingHasID: \& run_tests( \& "our JustHasID objects have ids", \& [ \*(AqJustHasID\*(Aq, \*(AqTest::ThingHasID\*(Aq ], \& ); \& \& # ...but we can run two test routines against our UnixUser class \& run_tests( \& "unix users have dirs and ids", \& [ \*(AqUnixUser\*(Aq, \*(AqTest::ThingHasID\*(Aq, \*(AqTest::HasDirectory\*(Aq ], \& ); \& \& \& # We can still use the "attributes to initialize an object," and when doing \& # that it may be that we don\*(Aqt care to run all the otherwise applicable tests, \& # because they\*(Aqre not interesting in the scenario we\*(Aqre creating. For \& # example... \& run_tests( \& "a trailing slash is okay in a directory", \& [ \*(AqUnixUser\*(Aq, \*(AqTest::HasDirectory\*(Aq ], \& { dir => \*(Aq/home/meebo/\*(Aq }, \& ); \& \& # ...and we\*(Aqre done! \& done_testing; .Ve .SH "AUTHOR" .IX Header "AUTHOR" Ricardo Signes .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2010 by Ricardo Signes. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.