Test::Standalone - Embed regression test suites in standalone scripts
# Normal operation $ script.pl ... # Regression test mode $ script.pl --test 1..3 ok 1 - Dies with non-existent files ... # ============================== #!/usr/bin/perl # ============================== use Test::Standalone; main(); sub main { # script code } =begin test # test code, only executed if script # gets called with --test option use Test::More tests => 3; use Test::Exception; @ARGV = ("/tmp/does/not/exist"); throws_ok { main() } qr/No such file/, "Dies with non-existent files"; ... =end test
Test::Standalone helps embedding regression test suites into standalone scripts without disrupting them.
Test::Standalone
During normal operation, the test suite doesn't even get compiled. It can use all kinds of fancy test modules which don't need to be present for the script to operate in normal mode. Only when the script gets called with the --test option, a source filter kicks in and executes the test suite embedded between these POD directives:
--test
=begin test ... =end test
If the following script gets called with one or more file names, it prints out the byte sizes of these files:
$ script.pl /etc/passwd /etc/group /etc/passwd has 2900 bytes /etc/group has 935 bytes
If it gets called with the --test option, the embedded test regression suite gets executed:
$ script.pl --test 1..2 ok 1 - Test STDOUT ok 2 - Check with -s ok 3 - Dies with non-existent files
Here's the code. Note how it uses main() to call the script's main code and how the test suite uses main() and @ARGV to run the script with different arguments and to check its STDOUT output with Test::Output:
main()
@ARGV
Test::Output
use Test::Standalone; main(); sub main { for my $file (@ARGV) { print "$file has ", -s $file, " bytes\n"; } } =begin test use Test::More tests => 2; use File::Temp qw(tempfile); my($fh, $file) = tempfile(); print $fh "123"; close $fh; @ARGV = ($file); use Test::Output; stdout_is(\&main, "$file has 3 bytes\n", "Test STDOUT"); is(-s $file, 3, "Check with -s"); @ARGV = ("/tmp/does/not/exist"); use Test::Exception; throws_ok { main() } qr/No such file/, "Dies with non-existent files"; =end test
It works like this: use Test::Standalone calls the import function in Test::Standalone, which invokes a source filter on the main script.
use Test::Standalone
import
It is paramount that the main body of the script is encapsulated in a function called main and that main gets called by the script at the beginning.
main
The import function checks if the --test command line option was set. If not, it does nothing and lets the script resume its normal operation.
If --test command line option is set, however, the source filter kicks in and extracts the test suite code embedded between the =begin test and =end test directives. Also, it rewrites the call to main() to Test::Standalone::test_run(). This will run the test suite instead of the script.
=begin test
=end test
Test::Standalone::test_run()
The test script runs in the main namespace. Tests in the test suite are typically run by setting @ARGV (therefore setting different command line parameters) and then running main() to execute the script. The test suite can employ all kinds of test modules, Test::More, Test::Output, Test::Exception and many more. They are not required during normal operation of the script, typically only for the script developer running the regression test suite.
Test::More
Test::Exception
Copyright 2005 by Mike Schilli, all rights reserved. This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself.
2006, Mike Schilli <cpan@perlmeister.com>
To install Test::Standalone, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Test::Standalone
CPAN shell
perl -MCPAN -e shell install Test::Standalone
For more information on module installation, please visit the detailed CPAN module installation guide.