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?
Similar... (Score:1)
http://search.cpan.org/dist/Test-Inline/lib/Test/Inline.pm [cpan.org]
Re: (Score:2)
Test::Inline and selftest are similar in that they both follow the idea of embedding the tests into the code being tested. Test::Inline focuses on putting the t
Re: (Score:1)