The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Test::Inline::Tutorial - Tutorial docs for Test::Inline

DESCRIPTION

Test::Inline is a way to embed tests in the same file as your source code rather than in a seperate file. The idea is, the closer your tests are to your code and docs, the more likely you'll keep them up to date.

How?

1

Install Test::Inline, but you've probably already done that. Test::Inline will install Test::More and Test::Simple.

2

Find some code you want to test. Test::Inline works best if this code has its documentation in an inline style, so each subroutine has its documentation right above it like so:

    =item B<is_pirate>

        my @pirates = is_pirate(@arrrrgs);

    Go through the @arrrgs and return a list of those who are
    pirates.

    =cut

    sub is_pirate {
        ...you didn't think I was going to implement this?...
    }
3

Read the docs for Test::Simple and Test::More if you haven't already. You'll be making use of its ok() and is() functions.

4

Okay, time to write a test. Its pretty straightforward, you're simply adding a testing block to your POD. This is done either with =for testing like so:

    =for testing
    is( 2 + 2,  4,         'I can add!' );

or a =begin testing/=end testing block.

    =begin testing

    my $hell = Geo::Weather->new('Hell');
    ok( $hell->temp > 0,       'Hell not yet frozen over' );
    ok( $hell->elevation  < 0, '  and still safely underground' );

    =end testing

Which to use? =for is best for single tests, =begin/=end for a series of them. Whichever feels better to you, doesn't really matter.

Its best to put the test right next to the documentation its testing.

    =item B<is_pirate>

        my @pirates = is_pirate(@arrrrgs);

    Go through the @arrrgs and return a list of those who are
    pirates.

    =for testing
    my @p = is_pirate('Roberts', 'Wesley', 'Capt. Hampton');
    is( @p,    1,                'Found our scurvy dog' );
    is( $p[0], 'Roberts',     '  The Dread Pirate Roberts!' );

    =cut

    sub is_pirate {
        ...still not gonna do it...
    }
5

Tests are written, now how to run them? Use pod2test to extract your test and produce a file.

    pod2test lib/Pirate.pm t/Pirate-embedded.t

Pirate-embedded.t will run just like any other test file.

6 *optional*

If you're writing a module, add your new test file to the MANIFEST. You will also have to add a Test::More as a PREREQ_PM in your Makefile.PL since this is what pod2test uses.

7 *optional*

You can automate the generation of your tests in a couple of ways. The simplest is to stick something like this into your Makefile.PL.

    system('pod2test lib/Pirate.pm t/Pirate-embedded.t');

but then you have to re-run Makefile.PL every time you change the file. To make it do it as part of "make test" you need this:

    {
        package MY;
        sub top_targets {
            my($self) = @_;
            my $out = "POD2TEST_EXE = pod2test\n";

            $out .= $self->SUPER::top_targets(@_);
            $out =~ s/^(pure_all\b.*)/$1 testifypods/m;

            $out .= "\n\ntestifypods : \n";

            foreach my $pod (keys %{$self->{MAN1PODS}},
                             keys %{$self->{MAN3PODS}})
            {
                (my $test = $pod) =~ s/\.(pm|pod)$//;
                $test =~ s|/|-|g;
                $test =~ s/^lib\W//;
                $test =~ s/\W/-/;
                $test = "embedded-$test.t";
                $out .= "\t$self->{NOECHO}\$(POD2TEST_EXE) ".
                        "$pod t/$test\n";
            }

            return $out;
        }
    }

I'm working on making #6 and #7 a bit more seamless, it's a work in progress.

That's the basics. There are further features like testing code examples:

    =also begin example

    print "Hello, World!\n";
    warn  "Beware the Ides of March!";

    =also end example

    =for example_testing
    is(   $_STDOUT_, "Hello, World!\n",               'print' );
    like( $_STDERR_, qr/^Beware the Ides of March!/,  'warn'  );

If you want to read more, see Test::Inline.

FAQ

Will this slow down my program/use more memory?

Nope. Perl considers the tests to be POD, so it completely ignores them (and no, inlined POD doesn't slow down your program's compilation).

Do I still have to write regular tests?

Probably. Embedded tests seem to be most useful for simple, direct, short tests. For example, testing each feature promised in your documentation. It's not good for big tests, anything requiring a lot of setup, or for testing many features interacting. Those should probably go into a seperate file.

If I write a module with embedded tests, does it depend on Test::Inline?

Oddly enough, no. You can write a program with embedded tests and distribute it without requiring Test::Inline. Simply generate the .t files with pod2test and distribute them normally with your code like any other?

However, it does require Test::More and the latest version of Test::Harness. Fortunately, these will be in 5.8.0. Unfortunately, you'll probably have to wait three years before everyone's using that.

AUTHOR

Michael G Schwern <schwern@pobox.com>

SEE ALSO

Test::Inline, Pod::Tests, pod2test

Short set of slides on Test::Inline http://www.pobox.com/~schwern/talks/Embedded_Testing/