I will spend few words on this, just showing you the code that works for me and can be adapted to your needs ... so lets talk more Perlish than English :^)
I used the core module Module::Pluggable to get all packages under, for instance, the PNI::Node namespace where there will be all my PNI "nodes" i.e. plugins implementing the PNI::Node interface (that has simply two abstract method init and task ) .
I choose the following naming convention :
the PNI::Node::Foo::Bar::My_node_name
has
the test _node-foo-bar-my_node_name.t
Here it is a PNI::Find package which holds a static method called nodes that returns a list containing all the packages under the PNI::Node namespace . PNI::Find is a singleton, but don't care about that by now, it is just a convenience to call PNI::Find->nodes from my meta test ( see below ) .
package PNI::Find;
use strict;
use warnings;
our $VERSION = '0.12';
use Module::Pluggable search_path => 'PNI::Node', require => 1, inner => 0;
# singleton
my $self;
sub new {
if ( not defined $self ) {
$self = bless \__PACKAGE__, __PACKAGE__;
}
return $self;
}
sub nodes {
my @nodes;
for my $module ( $self->plugins ) {
if ( $module->isa('PNI::Node') ) {
push @nodes, $module;
}
}
return @nodes;
}
1;
The following test script, called every_node_has_a_test.t, checks that under the t directory there is a test file for every node ( or plugin in your case ) .
use strict;use Test::More;use File::Spec;use PNI::Find;if ( not $ENV{TEST_AUTHOR} ) {my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.';plan( skip_all => $msg );}my $find = PNI::Find->new;my @core_nodes_dirs;my $node_dir_path = File::Spec->catfile(qw(lib PNI Node));opendir my ($node_dir_handle), $node_dir_path;for my $entry ( readdir $node_dir_handle ) {# looking or dirs starting with an uppercase letternext unless -d File::Spec->catfile( $node_dir_path, $entry );next unless $entry =~ /^[A-Z][a-z]+/;push @core_nodes_dirs, $entry;}my $core_nodes_dirs_regexp = join '|', @core_nodes_dirs;for my $node_class ( $find->nodes ) {# skip check on nodes not included in PNInext if $node_class !~ /^PNI::Node::($core_nodes_dirs_regexp)/;# naming convention for test of PNI::Node::Foo::Bar is _node-foo-bar.tmy $node_test = $node_class;$node_test =~ s/^PNI:://;$node_test =~ s/::/-/g;$node_test = lc "_$node_test.t";my $test_path = File::Spec->catfile( 't', $node_test );ok -e $test_path, "$node_class has a test";}done_testing;
Conclusion
Test driven development is a must, that's why I think it is necessary to check that there is at least a test for every module specially if you can't know a priori how much will be populated a namespace, for example if you decide to have plugins .
Next step would be to code some helper to create your modules ... mmhh I'm going to open some good CPAN module like Mojolicious and steal some code :-)
No comments:
Post a Comment