Sometimes getting test coverage where it ought to be can be a little tedious, at least with a highly dynamic language. I have an object containing constant data and synthetic attributes calculated from the constant data. It has about a dozen of these synthetic attributes:
has [ @plusses, @minuses ], is => 'ro', lazy_build => 1;
I use this skeleton for my testing code:
#! perl
use Modern::Perl;
use Test::More;
use lib 't/lib';
__PACKAGE__->main( 'Some::Module::To::Test' );
sub main
{
my ($test, $module) = @_;
use_ok( $module ) or exit;
$test->test_some_feature( $module );
$test->test_another_feature( $module );
$test->test_still_another_feature( $module );
$test->test_one_remaining_feature( $module );
done_testing();
}
sub default_args
{
my $self = shift;
return
(
default => 'Value',
for => 'example',
@_
);
}
sub test_some_feature
{
my ($test, $module) = @_;
my $obj = $module->new( $test->default_args );
...
}
Ultimately I should port these tests to Test::Class, but I don't quite need it yet. That does leave some repetition in typing the boilerplate code I need for each test method. If I were using an IDE which could resolve these method calls without having to run code, I'd let autocomplete generate this code for me.
It's only a couple of extra steps in Perl though:
sub AUTOLOAD
{
(my $name = our $AUTOLOAD) =~ s/main:://;
print STDERR <<END_HERE;
sub $name
{
my (\$test, \$module) = \@_;
my \$score = \$module->new( \$test->default_args );
}
END_HERE
}
With that AUTOLOAD
in place, I can run the test, redirect
STDERR to a file, then insert the contents of that file in the test file
itself. It's silly and it's simple, but it works.
You should look into Test::Routine as an alternative to Test::Class, it's quite nice.