如何防止Perl使用模块进行测试?
我正在开发一套Perl脚本和模块,然后部署到我们公司的不同机器和系统上。 某些设备依赖于特定模块,该模块可能安装在不同的机器上,也可能不安装在不同的机器上。我已使用“eval”检测此模块是否可用 我刚刚收到一份故障报告,归结为用户没有成功地在他的机器上安装模块(但没有意识到他没有):但我代码中的错误是,在这种情况下,我没有将错误条件传递到顶层,所以它丢失了,而脚本只是默默地无法执行其部分功能 为了进行调查,我禁用了机器上的特定模块,并很容易地发现并修复了问题。但除了卸载它,我能想到的唯一禁用它的方法是重命名文件(当然,这是我必须通过sudo完成的) 我现在正在运行我所有的测试,但这个模块不可用,并且它引发了一些其他地方,我没有正确处理这种情况 但是我现在想做的是为这种情况编写一些测试:但是我如何明智地使这个模块在自动测试中暂时不可用呢。我真的不希望我的测试使用sudo来移动模块(我可能同时在机器上做其他事情) 有人知道我可以告诉Perl的一种方法吗“无论我在哪里尝试‘使用’或‘要求’它,为了测试目的,都找不到这个模块”如何防止Perl使用模块进行测试?,perl,testing,Perl,Testing,我正在开发一套Perl脚本和模块,然后部署到我们公司的不同机器和系统上。 某些设备依赖于特定模块,该模块可能安装在不同的机器上,也可能不安装在不同的机器上。我已使用“eval”检测此模块是否可用 我刚刚收到一份故障报告,归结为用户没有成功地在他的机器上安装模块(但没有意识到他没有):但我代码中的错误是,在这种情况下,我没有将错误条件传递到顶层,所以它丢失了,而脚本只是默默地无法执行其部分功能 为了进行调查,我禁用了机器上的特定模块,并很容易地发现并修复了问题。但除了卸载它,我能想到的唯一禁用它的
我正在运行Perl5.10.0(在Fedora12上),并使用Test::More和TAP::Harness。我们的一些安装正在运行Perl5.8,因此我愿意在测试中使用5.10特性,但不在代码本身中使用 有几个CPAN模块正在这样做。我经常使用的是。另一个是。这两个人,以及其他几个我现在记不清名字的人,都以几乎相同的方式工作,通过
@INC
或CORE::GLOBAL::require
连接到perl的模块加载。详细信息记录在perldoc-f require中,正如rafl所说,有一些模块可以做到这一点
如果你对它的机制也感兴趣(除了获得结果之外),有两种方法可以做到这一点:
@INC
数组的一部分,该数组在通过use
/require
加载模块时使用。在文本中搜索“hooks”一词可以找到这一理论的基础# The following code was not tested - for illustrative purposes only
# MUST be done in the BEGIN block at the very beginning of the test
# BEFORE any "use Module"; lines
push @INC, \&my_sub;
my %prohibited_module_files = map { $_=> 1} ("Foo/Bar.pm", "x.pm");
# Ideally, translate module names into file names
sub empty_module_sub {
$_ = "1;\n"; # Empty module
return 0; # End of file
}
sub my_sub {
my ($coderef, $filename) = @_; # $coderef is \&my_sub
if ($prohibited_modules{$filename}) {
print STDERR "NOT loading module $filename - prohibited!\n";
# Optionally, die here to simulate not finding the module!!!
# Otherwise, load empty package
return (undef, \&empty_module_sub);
}
return undef; # Continue searching @INC for good modules.
}
稍微简单一点(但没有那么有趣或灵活)的方法依赖于这样一个事实,即“require”语义首先检查
$INC{$filename}
,如果该键存在于%INC散列中,则认为要加载模块;如果键映射到真值,则认为模块已正确加载,而假值则会导致“编译失败”类型的错误。因此,您可以实现与上面的自定义子项类似的结果,在适当的键(文件名与模块名匹配)下插入unde
或1
值在代码开头的BEGIN
块中插入%INC
。注意Test::Without::Module
也需要挂钩。它只是碰巧有一些额外的魔力,使已经加载的模块看起来好像从未加载过一样,这取决于您对它们的观察程度。@rafl-好的,需要重新读取POD/源。。。没注意到,谢谢!另外,它是否会“要求”死亡?注意:上面的示例代码将在它的目的中失败,如果您的代码在执行这个示例之后执行任何聪明的<代码> @ INC > /代码>操作,它将预处理到<代码> @ INC >代码(在您刚才插入的自定义子例程之前)。NOT2:还需要考虑是否要传播到子进程。(通过设置$ENV{PERL5OPT}
)-像往常一样,真正可靠的代码的魔鬼在于细节,这就是为什么,撇开自我教育不谈,CPAN模块通常应该用于实际用途的原因-Devel::Hide这样做,例如:)它不会死在要求的中,如果这是你要问的,但它确实会导致require
通过向其提供带有错误返回值的内容来引发异常本身。通常,您可以通过安装并使用自己的PERL进行测试来绕过sudo问题。我建议你假装系统管理员不在那里。