Stories
Slash Boxes
Comments

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

schwern (1528)

schwern
  (email not shown publicly)
http://www.pobox.com/~schwern/
AOL IM: Michael Schwern (Add Buddy, Send Message)
Yahoo! ID: schwern (Add User, Send Message)

Journal of schwern (1528)

Wednesday April 23, 2008
07:59 PM

Embedding tests in a script

[ #36235 ]
From time to time I'll work on a code base that's basically a pile of individual scripts. The process of converting it to a modularized system can take some time, technically as well as socially. Meanwhile, I have to get work done. And for me getting work done requires writing tests.

But if it's a pile of scripts, where do you put them? And with no build structure, how do you run them? Rather than having to decide between using a single file OR writing tests, I decided to embed the tests in the scripts themselves. Observe.

sub selftest {
    my @test_functions = get_test_functions();
 
    for my $function (sort { lc $a cmp lc $b } @test_functions) {
        no strict 'refs';
        print "# Running $function\n";
        &{$function};
    }
}
 
sub get_test_functions {
    my $package = shift || __PACKAGE__;
 
    # Load the test functions after __END__
    eval join '', <DATA>;
 
    no strict 'refs';
 
    return
      # Select only those which are subroutines
      grep { defined &{$_} }
 
      # Find the ones named test_*
      grep /^test_/,
 
      # Get all the symbols in the package
      keys %{$package."::"};
}
 
use Getopt::Long;
 
sub main {
    my %options;
    GetOptions(
        \%options,
        "test",
    );
 
    if( $options{test} ) {
        selftest();
        exit;
    }
 
    ... rest of the code here ...
}
 
main();
 
__END__
# These tests will be compiled and run when --test is given
 
use strict;
use warnings;
 
use Test::More 'no_plan';
 
sub test_the_tests {
    pass("The tests run!");
}
Giving a --test compiles the __END__ code (in selftest()), finds all the test_* functions, runs them and exits.

By embedding the tests into the scripts you can introduce unit testing to single-file scripters without having to simultaneously introduce the concept of a multi-file project. By putting the tests after the __END__ block nobody can make the excuse that your test functions are wasting memory in production.

I'm sure I'm not the first to come up with this, but I don't know that I've seen it modularized. So before I go and do that, is this already on CPAN?
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.