2011-08-01 24 views
1

我目前正在学习单元测试。为此,我正在写一个脚本,并为整个脚本创建单元测试。到目前为止事情进展顺利,但我试图测试从命令行输入脚本的不正确数据触发帮助信息。如何用Try :: Tiny“捕捉”Perl脚本中的pod2usage出口?

我的代码看起来是这样的:

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块。有没有办法解决这个问题,还是应该以不同的方式写我的测试?

回答

4

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

否则,exit也不例外,并且因此不象可捕获的异常。但是,它可以通过CORE::GLOBAL::exit覆盖。假设你正确定位你的修改,使用这是一个合理的方法。

或者,你总是可以启动一个子进程来运行你的整个脚本并捕获它的功能,根据你的测试,完全避免Pod::Usage调用exit的问题。

在一个相关的说明,您使用的是测试Try::Tiny的方式有点奇怪。我相信使用Test::Fatal(这是基于Try::Tiny)可能使在未来更清晰的测试。

+0

非常感谢你的回应,你会如何本地化CORE :: GLOBAL :: EXIT覆盖? – Moses

+0

使用“本地”内置。 – rafl

2

的问题是,pod2usageexit,而不是抛出异常。我不认为这可以被捕获。

为什么不叫测试整个脚本并检查返回值/输出与您的期望?

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. 
+0

我正在使用modulino方法来测试脚本。这允许我在测试中使用mock,这对于我正在编写的脚本(数据库访问,配置文件访问等)而言是必需的。 http://www252.pair.com/comdog/mastering_perl/Chapters/18.modulinos.html – Moses