24

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

还是有更好的方法来测试脚本?

4

7 回答 7

33

由于 brian 现在似乎睡着了,这里有一个指向他所谓的modulinos的指针。这基本上是构建像模块一样运行的脚本或可以像脚本一样运行的模块的秘诀。听起来与您正在寻找的完全一样。

Mastering Perl绝对是一本值得阅读(和购买)的书。

于 2009-01-22T12:32:16.807 回答
8

(我不想将脚本拆分为单独的模块和“可执行文件”,因为我打算将脚本作为单个文件分发。)

大多数人在构建时像这样将文件拼接在一起。CPAN 上的 App::Ack 就是一个可以这样构建的例子。

如果你真的想正确地测试你的应用程序,你需要把功能放在一个模块中,然后编写一个基于 Test::More 的测试脚本来练习模块提供的功能。然后实际的脚本只是模块的一个薄包装,通常是这样的:

#!/usr/bin/env perl
use Your::Class;
Your::Class->new(args => \@ARGV)->run;

另请参阅:MooseX::Getopt

于 2009-01-22T12:09:10.893 回答
4

我想做同样的事情。是否有理由不执行以下操作?(我不是 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 我抑制了 '#No tests run!' 使用 'use Test::More' 而不进行任何测试时收到的消息。我想它也减少了开销。)

于 2011-01-14T11:21:06.353 回答
2

这取决于您是要测试脚本本身,还是要测试组成脚本的子程序。如果您想测试脚本,那么外部测试会更合适,例如 shell 脚本。如果您想测试组成脚本的函数,那么您可以将这些测试编写为脚本中的更多函数,或者将元素重构为 Perl 模块并测试模块(您说您不想这样做) .

如果脚本足够小,则可能不需要重构。只需添加一个“-test”命令行参数并调用一个测试子程序,它反过来测试其他所有内容。如果这样做,我喜欢打印出某种进度指示器(例如,每个通过的测试都有一个“.”)。

但是,如果脚本更复杂,您可能需要考虑将位重构为一个或多个模块并使用Test::SimpleTest::More测试它们。

于 2009-01-22T12:14:18.137 回答
1

为什么不在 shell 脚本中编写一个测试套件,像任何其他 shell 命令一样调用 Perl 脚本?

于 2009-01-22T11:25:07.643 回答
0

因为我只是想测试一个子,我使用了将那个子提取到一个带有 perl 单行器的模块中的 hacky 解决方案,这很容易理解并且不需要安装任何模块(我提取了带有子的段落名字当然很脆弱)。所以在我的 Makefile 我有:

MyModule.pm: my_script.pl
    perl -00 -lnE 'if(/^\s*sub my_sub \{/){say "package MyModule;";say;say "1;";}' my_script.pl >|MyModule.pm
于 2019-04-10T07:57:50.780 回答
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;

这会将 subs 导入到测试的主命名空间中,并且可以轻松地进行测试。

编辑:在搜索了我一直在寻找的东西之后,我意识到modulinos基本上是我所做的,但避免通过 ENV 进行通信,将所有代码放在一个方法中并检查是否有调用者():

https://www.perlmonks.org/bare/?node_id=537377(先前答案中的链接似乎不起作用)

于 2020-11-10T02:06:48.900 回答