如何测试独立的Perl脚本?

时间:2009-01-22 10:57:25

标签: perl unit-testing scripting module

我编写了一个小的Perl脚本,现在我想为它创建一个测试套件。我认为能够use脚本作为模块,导入脚本中定义的子并测试它们会很好。有没有办法让脚本既可以是独立的Perl脚本,也可以是Perl模块? (我不想将脚本拆分为单独的模块和“可执行文件”,因为我打算将脚本作为单个文件分发。)

或者有更好的方法来测试脚本吗?

7 个答案:

答案 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::SimpleTest::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(上一个答案中的链接似乎无效)