Test::Inline::Tutorial - Tutorial docs for Test::Inline
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.
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?... }
ok()
and is()
functions.
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... }
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.
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.
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.
Michael G Schwern <schwern@pobox.com>
Test::Inline, Pod::Tests, pod2test
Short set of slides on Test::Inline http://www.pobox.com/~schwern/talks/Embedded_Testing/