Fun with App::Prove::Plugin

Steve Purkis steve at purkis.ca
Tue Feb 3 08:23:27 GMT 2009


Hi all,

I've finally written an App::Prove plugin for TAP::Formatter::HTML  
(hooray for snow days!).  I'm sharing my thoughts, as promised moths  
ago:

The good news is: it works!

It was pretty easy to write a plugin.  I just used  
App::Prove::Plugin::Tagged as an example, and poked under the hood of  
App::Prove to find out how the cmdline scraping worked - pretty  
straightforward.

But I came away with 2 annoyances with the App::Prove plugin system:

1. You can't change the behaviour of the app very easily without  
setting globals / environment variables.
2. You can't change what cmdline params are accepted.

As an example, I currently have to ask the user to type this:

  % prove -PHTML=output.html -m --formatter=TAP::Formatter::HTML

When I'd rather have them type this:

  % prove -PHTML=output.html

Or even better:

  % prove --html=output.html

In both of these cases, I'm assuming that the formatter class,  
TAP::Formatter::HTML, would be set by the App::Prove::Plugin::HTML  
module.  I'm also assuming the plugin could check whether or not '-m'  
was passed, and default to true if the user didn't explicitly turn it  
off.

In the last case, I'm assuming the plugin could add it's own cmdline  
params, to be parsed by GetOptions.  Yes, I know the plugin hasn't  
even been loaded at this point.  I was thinking it might be possible  
to pre-load plugins (or at least, plugins' cmdline parsing options),  
which would involve scanning for available plugins, and making several  
fancy guesses after parsing the cmdline opts about which plugins to  
load finally.  This might be OTT to start with, not to mention crack- 
fueled.  A nice-to-have, at best.


So, concentrating only on annoyance #1 I came up with a pretty simple  
idea - pass the App::Prove object to the plugin on import:

sub _load_extension {
     ...
     if ( my $name = $self->_find_module( $class, @search ) ) {
         $name->import({ app_prove => $self, args => [ @args ] });
     }
     ...
}

This would make it possible to set whatever you like on the app before  
TAP::Harness ever gets called.  IE: a lot of flexibility for one lazy  
line of code.  Of course, that would break current plugin API... but  
then, I can only see 1 other module on CPAN that uses it.

Thoughts?

Cheers,
+--
   Steve Purkis



More information about the tapx-dev mailing list