So you have a program that contains routines which should really be in a library. You want to run those routines separately to test them. You don't want to run the program, of course. Or, worse, you want to run those routines for actual production use (you should be shot) without running the program.
I found out how to do this in the middle of the night a couple of weeks ago, from a presentation somebody linked to from here. Jotted down some notes, and now I'm putting it here so I can find it later. :)
require($program); import qw(routine routine routine);
Or, for testing:
require_ok($program); import qw(routine routine routine) ok(routine(1, 2));
This just gets at what the use
keyword does, internally.
Update: Okay, this is apparently wrong. :) I didn't try it out at all, though I may have need to at some point. I'm going to leave it here to remind me that this is theoretically possible, although given what dakkar pointed out, it may not be.
Which means somebody's slides were way off. :) (Or else I was completely asleep and didn't understand.)
Let's say you have this prog.pl:
#!/usr/bin/perl
sub do_something {
return 42;
}
print "Running\n";
and this test.pl:
#!/usr/bin/perl
require 'prog.pl';
print "ok 1\n" if do_something()==42;
Now, running test.pl produces:
Running
ok 1
because the require will execute the program. So, if the program dies because @ARGV is wrong, or somesuch, your test dies as well...
It'll work now.unless(caller) {
# former top level
print "Run as a script\n";
} else {
# you may drop this if you don't need it
print "Initializing as a library file\n";
}
Re:What you should do is change the program
jdavidb on 2007-05-15T15:47:51
Thank you. Sounds like this advice was either present in the slides I read, and I missed it (it was middle of the night, up late hacking for work
:) ), or else the presenter missed it or only mentioned it orally without including it in the slides.
Besides your update, import()
is a method. When you call methods as functions in Perl, you don't always get what you want.
I think you'll have more luck checking caller()
to see if someone has invoked your program directly.
int main(void)
). Now a program is just a set of subroutines and you can use it like every other library of subroutines (including testing it).Hopefully it wasn't my slides that were way off
phred@pooky ~ $ cat program.pl
#!perl -w
use strict;
use warnings;
our $var = 0;
sub addition {
my ($one, $other_one) = @_;
my $result = $one + $other_one+$var;
return $result;
}
sub should_die {
die "oops";
}
1;
phred@pooky ~ $ cat foo.t
#!perl
use strict;
use warnings FATAL => 'all';
use Test::More tests => 3;
my $class = 'program';
require_ok("$class.pl");
import $class qw( addition should_die);
no strict 'refs';
${"main\:\:var"} = 5;
my $method = 'addition';
cmp_ok($method->(1,1), '==', 7, '1+1+var returns 7');
$method = 'should_die';
eval { $method->() };
like($@, qr/oops/i, 'should_die() died');
Re:Here's how I did it
Phred on 2007-05-15T22:23:10
Oops, I forgot the output
phred@pooky ~ $ perl foo.t
1..3
ok 1 - require 'program.pl';
ok 2 - 1+1+var returns 7
ok 3 - should_die() died