如何使用Try :: Tiny“捕获”Perl脚本中的pod2usage出口?

时间:2011-08-01 15:05:26

标签: perl unit-testing try-catch

我目前正在尝试学习单元测试。为此,我正在编写脚本,我正在为整个脚本创建单元测试。到目前为止,事情进展顺利,但我正在尝试测试从命令行触发帮助消息的脚本中输入的错误数据。

我的代码类似于:

sub getContext{
   my ($help) = @_;

GetOptions(
  help|h => \$help,
   ...

pod2usage if $help;
... 
}

我的测试看起来像:

my $help_exception = 0;
try{  
   getContext( {help => 0} );
}catch{
 $help_exception = 1; 
}

ok($help_exception, "Script died correctly when given help flag");

我的输出看起来非常类似于:

1..4

ok 1 - use scripts::scriptname;

ok 2

ok 3

# Looks like you planned 4 tests but ran 3.

# Looks like your test exited with 1 just after 3.

帮助标志的测试是测试4,看起来我的脚本正在退出而没有触发Try :: Tiny try catch块。有没有办法解决这个问题,还是我应该以不同的方式编写测试?

3 个答案:

答案 0 :(得分:4)

Pod::Usage关于它的-exitval参数的文档显示了如何阻止它一起退出。您可以简单地使用它并相应地调整代码和/或测试。

否则,exit不是例外,因此不像特例那样可以捕获。但是,它可以通过CORE::GLOBAL::exit覆盖。使用它也是一种合理的方法,假设您正确地对您的修改进行了本地化。

或者,您始终只需启动一个子流程来运行整个脚本并捕获它的功能,并根据它进行测试,完全避免Pod::Usage调用exit的问题。

在相关的说明中,您在测试中使用Try::Tiny的方式有点奇怪。我相信使用Test::Fatal(基于Try::Tiny)可能会在将来进行更清晰的测试。

答案 1 :(得分:2)

问题是pod2usage执行了exit而没有抛出异常。我认为不能以这种方式捕捉它。

为什么不在测试中调用整个脚本并检查返回值/输出是否符合您的期望?

答案 2 :(得分:1)

正如bvr回答的那样:程序/脚本实际上不是单元可测试的,因为它不是由可重复使用的部件/单元组成。你应该从整体上进行测试。使用命令行参数执行它并检查其输出和错误。例如,使用Capture::Tiny -

use warnings;
use strict;
use Capture::Tiny qw( capture );
use Test::More;

my $script = "/bin/ls";

plan skip_all => "Have no `$script` to check"
    unless -x $script;

my ( $out, $err ) = capture {
    system($script, "-1", "/");
};

like( $out, qr{^bin$}m, "$script finds bin" );
ok( ! $err, "...without error" );

done_testing(2);

prove -

的输出
/home/apv/ab ..
ok 1 - /bin/ls finds bin
ok 2 - ...without error
1..2
ok
All tests successful.