tags:

views:

100

answers:

3

How do I write a test in Perl to see if my file was run directly or imported from some other source? I'd like to do this to make it easy to bundle everything in one file but still write unit tests against the functions. My idea is to have something like this:

if (running_directly()) {
  main();
}

def main {
  this();
  that();
}

def this {
  # ...
}

def that {
  # ...
}

Then in a separate perl script I can load the original file and call this & that as unit tests.

I remember seeing this done before, but I can't remember how to do it. I'd like to avoid testing $0 against some known value, because that means the user can't rename the script.

+7  A: 

First of all, Perl doesn't have a def keyword. :)

But you can check if a module is being executed directly or included elsewhere by doing this:

__PACKAGE__->main unless caller;

Since caller won't return anything if you're at the top of the call stack, but will if you're inside a use or require.

Some people have assigned the dreadful neologism "modulino" to this pattern, so use that as Google fuel.

friedo
Mayhap he's using Rubyish::Syntax::def
daotoad
Oops, too much python! :-)
Paul A Jungwirth
+1  A: 

See my related question about testing Perl scripts. You might also be interested in running a REPL with the module in question:

package REPL;

use Modern::Perl;
use Moose;

sub foo {
    return "foo";
}

sub run {
    use Devel::REPL;
    my $repl = new Devel::REPL;
    $repl->load_plugin($_) for qw/History LexEnv Refresh/;
    $repl->run;
}

run if not caller;

1;

And then on the command line:

$ perl REPL.pm
$ REPL->new->foo;
bar
^D
$ perl -MREPL -E "say REPL->new->foo"
bar
zoul
+4  A: 

You might be thinking of brian d foy's "modulino" recipe, which allows a file to be loaded either as a standalone script or as a module.

It is also described in greater depth in his "Scripts as Modules" article for The Perl Journal as well as "How a Script Becomes a Module" on Perlmonks.

Ether