我编写了一个小的Perl脚本,现在我想为它创建一个测试套件。我认为能够use
脚本作为模块,导入脚本中定义的子并测试它们会很好。有没有办法让脚本既可以是独立的Perl脚本,也可以是Perl模块? (我不想将脚本拆分为单独的模块和“可执行文件”,因为我打算将脚本作为单个文件分发。)
或者有更好的方法来测试脚本吗?
答案 0 :(得分:32)
由于布莱恩现在似乎已经睡着了,所以这里指的是他所谓的modulinos。这基本上是构建脚本的配方,这些脚本就像模块或模块一样可以像脚本一样运行。听起来和你想要的完全一样。
Mastering Perl绝对是一本值得阅读(和购买)的书。
答案 1 :(得分:6)
(我不想将脚本拆分为单独的模块和“可执行文件”,因为我打算将脚本作为单个文件分发。)
大多数人在构建时将文件拼接在一起。 App :: Ack on CPAN是一个可以像这样构建的例子。
如果您确实想要正确测试应用程序,则需要将功能放在模块中,然后编写一个Test :: More-based测试脚本来运行模块提供的功能。然后实际的脚本只是模块周围的一个薄包装器,通常类似于:
#!/usr/bin/env perl
use Your::Class;
Your::Class->new(args => \@ARGV)->run;
另请参阅:MooseX::Getopt。
答案 2 :(得分:3)
我想做同样的事情。有没有理由不做以下事情? (我不是perl专家,但解决方案似乎对我来说很好。):
在脚本的开头我要求切换(“-test”)或者其他什么,而不是分支到这样的子:
my $myargs = CmdLineOptions->new( args=>\@ARGV );
if ($myargs->was_given(option=>"-test")) { &tests; }
sub tests {
require "Test/More.pm";
Test::More->import('no_plan');
is(1,1,"my tests go here");
exit;
}
(通过使用require和import,我可以在不进行任何测试的情况下使用'use Test :: More'来消除'#No tests run!'消息。我想这也可以减少开销。)
答案 3 :(得分:2)
这取决于您是要测试脚本本身,还是测试构成脚本的subs。如果你想测试脚本,那么外部测试会更合适,例如一个shell脚本。如果要测试构成脚本的函数,那么您可以将这些测试编写为脚本中的更多函数,或者将元素重构为Perl模块并测试模块(您说您不想这样做)
如果脚本足够小,则可能不需要重构。只需添加一个'-test'命令行参数并调用一个test sub,然后测试其他所有内容。如果这样做,我喜欢打印出某种进度指示器(例如,对于每次通过的测试都是'。'。
如果脚本更复杂,您可能需要考虑将位重构为一个或多个模块,并使用Test::Simple或Test::More对其进行测试。
答案 4 :(得分:1)
为什么不在shell脚本中编写测试套件,Perl脚本调用就像任何其他shell命令一样?
答案 5 :(得分:0)
由于我只想测试一个潜水艇,所以我使用了一种hacker解决方案,该解决方案使用perl单线将潜水艇提取到模块中,这很容易理解,不需要安装任何模块(我提取了该段子名称当然很脆)。所以在我的Makefile中,我有:
$ sed -E -n '/ERROR/{s@/.*@@;h;n;n;H;n;H;x;s/\n//;p}' input.log
some message 1234556
more info foo bar
答案 6 :(得分:0)
尽管使一些CGI样式的perl脚本可远程测试(不通过CGI测试模块循环),但我最终做了这样的事情:
bin / myscript.pl:
use …;
do {
return 1 if $ENV{INCLUDED_AS_MODULE};
… original script without the subs …
};
sub some_sub {
…
}
sub …
sub …
t / mytest.t:
use Test::More;
use FindBin qw/$Bin/;
BEGIN {
$ENV{INCLUDED_AS_MODULE} = 1;
my $filename = "$Bin/../bin/myscript.pl";
do $filename or die "Unable to open '$filename': $! ($@)";
}
ok some_sub(), 'some sub returns true';
…
done_testing;
这会将子项导入测试的主命名空间,并且可以轻松进行测试。
编辑:在进一步搜索了我要寻找的内容之后,我意识到modulinos
基本上就是我所做的,但是避免了通过ENV进行通信,而是将所有代码放入一个方法中并检查是否有一个caller():
https://www.perlmonks.org/bare/?node_id=537377(上一个答案中的链接似乎无效)