Wednesday 19 June 2013

Testing perl scripts

With the help of my colleagues Daria Gordon and Bhavana Harsha and the book 'Perl Testing: A Developer's Notebook', I've been learning how to test perl scripts.

Testing a simple 'Hello world!' perl subroutine using ok() from Test::Simple
Here is a very simple testing script hello.t with subroutines to print out 'Hello world!' and 'Hello universe!', and a test of each subroutine:

#!perl

use strict;
use warnings;


use Test::Simple tests => 2;

sub hello_world
{
   return "Hello world!";
}


sub hello_universe
{
   return "Hello universe!";


ok( hello_world() eq "Hello world!", 'Test 1: check hello_world() output is ok');

ok( hello_universe() eq "Hello universe!", 'Test 2: check hello_universe() output is ok');

Here the subroutine and the test are all in one file.
The test can be run by typing:
% prove hello.t
hello.t .. ok 
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.02 usr  0.00 sys +  0.01 cusr  0.00 csys =  0.03 CPU)
Result: PASS

You can get more information on each of the tests run by typing:
% prove -v hello.t
hello.t ..
1..2
ok 1 - Test 1: check hello_world() output is ok
ok 2 - Test 2: check hello_universe() output is ok
ok
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.02 usr  0.01 sys +  0.01 cusr  0.00 csys =  0.04 CPU)
Result: PASS


A perl module for the 'Hello world!' subroutine
A more normal way to do things is to put the subroutines in a separate module file, eg. Hello.pm:

package Hello;

use strict;
use warnings;

use base 'Exporter';
our @EXPORT_OK = qw( hello_world hello_universe );

sub hello_world
{
   return "Hello world!";
}

sub hello_universe
{
   return "Hello universe!";
}

1;


Testing the 'Hello world!' perl module using ok(), use_ok() and can_ok()
Then you can use this testing script hello2.t to test the subroutines in the module:

#!perl

use strict;
use warnings;

use Test::More tests => 5;

# Specify the subroutines to import:
my @subs = qw (hello_world hello_universe);

# Check we can import the subroutines:
use_ok( 'Hello', @subs);
can_ok( __PACKAGE__, 'hello_world');
can_ok( __PACKAGE__, 'hello_universe');

# Test the subroutines:
ok( hello_world() eq "Hello world!", 'Test 4: check hello_world() output is ok');
ok( hello_universe() eq "Hello universe!", 'Test 5: check hello_universe() output is ok');


We run the testing code by typing:
% prove hello2.t
hello2.t .. ok  
All tests successful.
Files=1, Tests=5,  0 wallclock secs ( 0.02 usr  0.01 sys +  0.02 cusr  0.00 csys =  0.05 CPU)
Result: PASS

For more details, we type:
% prove -v hello2.t
hello2.t ..
1..5
ok 1 - use Hello;
ok 2 - main->can('hello_world')
ok 3 - main->can('hello_universe')
ok 4 - Test 4: check hello_world() output is ok
ok 5 - Test 5: check hello_universe() output is ok
ok
All tests successful.
Files=1, Tests=5,  0 wallclock secs ( 0.02 usr  0.00 sys +  0.02 cusr  0.00 csys =  0.04 CPU)
Result: PASS


Using the 'Hello world!' perl module in a perl script We can use the perl module in a perl script, eg. hello.pl:

#!/usr/bin/perl

use strict;
use warnings;
use Hello;

my $hello1 = Hello::hello_world();
print "$hello1\n";

my $hello2 = Hello::hello_universe();
print "$hello2\n";


When we run the perl script, we see:
% perl -w hello.pl
Hello world!
Hello universe!


Thanks to my colleagues Daria Gordon and Bhavana Harsha for lots of helpful discussion about this.

No comments: