2

我正在尝试测试包含在我的 Perl 发行版中的脚本。该脚本仅输出到文件,因此我的测试在运行它后会检查文件内容。我尝试按照这篇文章中的说明进行操作,但它对我来说不太奏效。我正在测试的脚本使用同一发行版中的模块,因此运行脚本需要以@INC某种方式添加模块的位置。我注意到Test::Script添加-Mblib 到参数中,所以我尝试了相同的方法。但是,它在开发过程中不起作用,因为没有 blib 目录。使用-Mblib使一切仅在dzil testor下工作make test。在开发过程中,我使用prove或简单地perl -Ilib t/test_script.pl使用,并尝试使用-Mblib导致测试失败和警告Cannot find blib even in C:\。考虑到这一点,我有几行代码缺少一个关键部分:

my $script_path = catfile( $FindBin::Bin, updir(), qw(scripts my_script.pl) );
my $include = 
    $HAS_BLIB && '-Mblib' || 
    '-I"' . catdir($FindBin::Bin, updir(), 'lib') . '"';
my $args = join ' ', map {qq["$_"]} @input_args;
my $command = qq{"$^X"  $include "$script_path" $args};
`$command`;
#test that script worked here...

我放什么而不是标量$HAS_BLIB?我需要一种方法来判断我是否正在构建发行版。欢迎其他意见。也许我有更好的方法来做这件事?我只是想要一种方法来测试同时通过 和 的prove脚本make test

4

2 回答 2

1

要回答这个问题,您可以使用 Module::Path 来检查分发中的任何模块文件是否在blib/lib目录中。这不是万无一失的,因为有人可能prove在另一个名为 的目录内的发行版上运行blib,但我认为这不太可能。这也有一个缺点,即要求发行版.pm在某处有一个文件,但情况可能并非如此。

或者,您可以检查保存该目录的t目录(在测试脚本中,这将$Bin来自FindBin)中是否有blib目录。但是,如果您在make没有运行make clean该脚本后又进一步开发了该脚本,则当您运行proveblib目录中的陈旧脚本时,仍将运行该脚本。

在我对我的问题的评论中,我提到了检查$INC{'blib.pm'}。这仅在使用 调用测试脚本时才有效-Mblib,并且make test不这样做。相反,它ExtUtils::Command::MM::test_harness使用blib/libblib/arch作为包含目录调用。

Once you know that you're running code out of blib, then you need to change both the include path, which should be blib/lib, and the script path, which should be blib/script/whatever (and no .pl if your script had one originally, because make removes it). So here's a correct version of the original example:

use Module::Path 'module_path';
use Path::Tiny;
use FindBin;
use Test::More;
plan tests => 1;
use Capture::Tiny;
my $module_path = path(module_path('My::Thing'));
my $HAS_BLIB =
    $module_path        #Thing.pm
        ->parent    #My
        ->parent    #lib
        ->parent    #blib
        ->basename eq 'blib';
my $script_path = $HAS_BLIB && path(qw(blib script my_script)) ||
    path(path($FindBin::Bin)->parent, 'bin', 'my_script.pl');
my $include = $HAS_BLIB && '-Mblib' || # could also do -Iblib/lib -Iblib/arch
    '-I'. path(path($FindBin::Bin)->parent, 'lib'); # would use installed version of C code
my @command = ($^X, $include, $script_path, @batch_files);
my ($stdout, $stderr) = capture {system(@command)};
is($stderr, '', 'no errors reported from script');
#more tests here

This is an awful lot of trouble, and in this case I don't think that it's necessary. I'm not entirely sure when it would be useful. If your distribution has C/C++ code then you might want to always use the blib solution, which adds blib/arch to the include path. With the above simple example, the test passes using the non-blib settings because the original files are still available. Little change happens to the files copied into the blib directory. So when I was debugging this, the only way I could tell if it was doing the right thing was to print out the full command used!

In other words, it wasn't very testable, and if someone really needs this then they should create a module to manage it (and test that). Test::Script seems to always use -Mblib, which would mean you could be using a stale make result, and you have to pass in the path of the script, meaning it's up to you to decide to whether to use the original script or the one inside blib/script.

于 2013-12-02T22:24:10.210 回答
-1

如果您只需要测试脚本是否已成功写入文件而不需要检查其内容,则可以在脚本中执行此操作。例如,Perl openreturns nonzero on successprint returns true if successful

捕获这些函数(或您正在使用的任何函数)的返回值,测试是否成功,并相应地设置脚本的退出值,然后对其进行测试。

于 2013-01-28T03:52:25.913 回答