我目前正在尝试学习单元测试。为此,我正在编写脚本,我正在为整个脚本创建单元测试。到目前为止,事情进展顺利,但我正在尝试测试从命令行触发帮助消息的脚本中输入的错误数据。
我的代码类似于:
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块。有没有办法解决这个问题,还是我应该以不同的方式编写测试?
答案 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.