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()
andis()
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' );
but they're experimental. 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/