Test Tutorial
Test Tutorial
print "1..1\n";
1..1
ok 1
◆ ext/Cwd/t/cwd.t
◆ t/pod/plainer.t
● Maintenance nightmare.
I'm ok, you're ok
#!/usr/bin/perl -w
ok( 1 + 1 == 2 );
1..2
ok 1
not ok 2
# Failed test (contrived.t at line 5)
# Looks like you failed 1 tests of 2.
#!/usr/bin/perl -w
use Date::ICal;
● This produces:
1..2
ok 1
ok 2
● This outputs
1..2
ok 1 - new() returned something
ok 2 - and it's the right class
What's In A Name
● Two views on names.
◆ A name is a descriptive tag so you can track the test output back to
the code which produced it. (the original purpose)
◆ A name is a short description of what was tested.
● There's a subtle difference.
● Don't pull your hair out over it.
◆ More importantly, don't pull other people's hair out over it.
Test The Manual
● Simplest way to build up a test suite is to just test what the
manual says it does.
◆ Also a good way to find mistakes/omissions in the docs.
◆ You can take this five steps further and put the tests IN the
manual. Test::Inline, later.
● If the docs are well written, they should cover usage of your
code.
◆ You do have docs, right?
SYNOPSIS
● A good place to start.
◆ A broad overview of the whole system
● Here's a piece of Date::ICal's SYNOPSIS.
SYNOPSIS
use Date::ICal;
$hour = $ical->hour;
$year = $ical->year;
$ical = Date::ICal->new(
year => 1964, month => 10, day => 16, hour => 16,
min => 12, sec => 47, tz => '0530' );
● Whoops, failures!
● We know what and where it failed, but not much else.
● How do you find out more?
◆ Throw in print statements
◆ Run in the debugger.
● That sounds like work.
Test::More
● Test::Simple is deliberately limited to one function.
● Test::More does everything Test::Simple does.
◆ You can literally s/use Test::Simple/use Test::More/
● It provides more informative ways to say "ok".
is() you is() or is() you isnt() my $baby;
● Test::More's is() function:
◆ declares that something is supposed to be something else
◆ "Is this, that?"
# From
# To
use Date::ICal;
$ical = Date::ICal->new(
year => 1964, month => 10, day => 16, hour => 16,
min => 12, sec => 47, tz => '+0530' );
my %ICal_Dates = (
'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 ],
);
ok 1
ok 2
ok 3
1..3
local $!;
ok( !open(FILE, "I_dont_exist"), 'non-existent file' );
isnt( $!, 0, ' $! set' );
my $warnings = '';
local $SIG{__WARN__} = sub { $warnings . join '', @_ };
local $@;
eval {
croak "Wibble";
};
like( $@, qr/^Wibble/ );
not ok 1
# Failed test (contrived.t at line 2)
# 'wibble'
# doesn't match '(?-xism:woof)'
◆ Might seem silly, but can catch stupid mistakes like forgetting a "=cut"
● Takes an object or a class.
● Also useful for checking your functions are exported
use Text::Soundex;
can_ok(__PACKAGE__, 'soundex');
use_ok()
● The real first thing you test is if the module loaded.
not ok 1
# Failed test (- at line 2)
# Structures begin differing at:
# $got->{that}[2] = '3'
# $expected->{that}[2] = Does not exist
t/array.............ok
t/chdir.............ok
t/var...............ok
All tests successful.
Files=3, Tests=48, 2 wallclock secs
( 1.71 cusr + 0.38 csys = 2.09 CPU)
ExtUtils::MakeMaker
Test::Harness
your test
What in the hell is all that mess?
PERL_DL_NONLAZY=1
-Iblib/lib -Iblib/lib
-I/usr/local/perl5.6.1/lib/5.6.1/ppc-linux-64int ...
● Mistake. Code specific for testing Perl itself that leaked out.
● Causes problems with core modules on CPAN.
● Fixed in latest versions of MakeMaker.
The mess continued...
-e 'use Test::Harness qw(&runtests $verbose);
$verbose=0
require HTML::Lint;
my $lint = HTML::Lint->new;
isa_ok( $lint, 'HTML::Lint' );
$lint->parse( $some_html );
is( $lint->errors, 0, 'No errors found in HTML' );
● Since HTML::Lint is optional, this test will fail if you don't have
it.
◆ But it's not a real failure, else HTML::Lint isn't really optional.
◆ So the user shouldn't hear about it.
# SKIP
● You can explicitly skip a set of tests rather than run them.
1..2
ok 1
ok 2 # SKIP no beer
◆ Test #1 passed.
◆ Test #2 was skipped because there is no beer.
● A skipped test means the test was never run.
SKIP: block
● Test::More can cause an entire block of code not to run at all.
SKIP: {
eval { require HTML::Lint };
$lint->parse( $html );
is( $lint->errors, 0, "No errors found in HTML" );
}
use Test::More;
if( $^O eq 'MSWin32' ) {
plan tests => 42;
}
else {
plan skip_all => 'Win32 specific test';
}
my $spoon;
URI::Geller->bend($spoon);
is( $spoon, 'bent', 'Spoon bending' );
}
sub should_i_sleep {
my($power_remaining) = @_;
sub snooze {
system("/sbin/snooze");
}
should_i_sleep($Min_Power - 1);
is( $snooze_called, 1, 'snooze called once' );
is( @snooze_args, 0, ' called properly' );
}
use DBI;
{
local *DBI::connect = sub {
return 0;
};