用于测试Perl脚本/模块异常和死亡的单元测试

时间:2015-07-15 11:53:18

标签: perl unit-testing exception perl-module die

我正在尝试使用Test::MoreTest::Exception库为我的脚本创建单元测试 我已阅读这些文章How to test for exceptions in PerlTest::Exception 第一篇文章准确描述了我需要的东西,以测试我的子程序抛出异常或死亡 但我无法让它发挥作用。考虑一些例子

    #!/usr/bin/env perl
    package My::SuperModule;
    use strict;
    use warnings;
    use Net::Ping;
    use Utils::Variables::Validator;

    sub new
    {
        die "Hello";
        #Getting class name from, stored in $_[0]
        my $class = shift;
        #Getting user name from arguments $_[1]
        my $user_name = shift;
    ........
}

我的测试文件

    use warnings;    # this warns you of bad practices
    use strict;      # this prevents silly errors
    use Test::More; # for the is() and isnt() functions
    use Test::Exception;
    do './My/SuperModule.pm';
    #Testing module loading 
    print "=================Testing module loading=================\n";
    use_ok ( 'My::SuperModule' );
    use_ok ( 'My::SuperModule', 'new' );
    #Testing module subroutines
    dies_ok { My::SuperModule->new() } "Died in class constructor";
     sub div {
    my ( $a, $b ) = @_;
    return $a / $b;
};
    dies_ok { div( 1, 0 ) } 'divide by zero detected';

它在任何情况下都停止执行脚本,但我只需要处理如果死了,我需要测试这个因为我手动调用die如果数据无效或其他东西,但它死了并且不会继续执行脚本进一步。给我留言

Uncaught exception from user code:
    Hello at ../libs/My/SuperModule.pm line 31.
    My::SuperModule::new('My::SuperModule', '') called at SuperModule.t line 24
# Tests were run but no plan was declared and done_testing() was not seen.
# Looks like your test exited with 2 just after 8.

但是如果要使用除零,它就像我想要的那样工作

ok 16 - divide by zero detected

因此它失败但不终止脚本的执行。

我是Perl的新手,所以不能自己解决问题,也许根本没有问题,只是没办法做我想做的事。
请在这里建议做什么或说出我的错。

修改

我刚尝试在我的模块新子程序中除以零,这是我得到的消息。

Illegal division by zero at ../libs/My/SuperModule.pm line 33 (#1)
    (F) You tried to divide a number by 0.  Either something was wrong in
    your logic, or you need to put a conditional in to guard against
    meaningless input.

我真的无法弄清楚发生了什么。请帮助解决这个问题。

2 个答案:

答案 0 :(得分:4)

这是一个有效的最小例子:

package My::SuperModule;
use strict;
use warnings;

sub new {
    die "Hello";
}

package main;

run() unless caller;

use Test::More;
use Test::Exception;

sub run {
    dies_ok { My::SuperModule->new } "dies ok";
    done_testing;
}

输出:

C:\...\t> prove -v my.pl
my.pl ..
ok 1 - dies ok
1..1
ok
All tests successful.
Files=1, Tests=1,  0 wallclock secs ( 0.09 usr +  0.00 sys =  0.09 CPU)
Result: PASS

请注意,为了提供一个自包含的示例,我将模块代码和测试脚本合并为一个文件。

另请注意,我没有使用不必要的print语句使测试脚本混乱。

如果需要,可以使用diag显示一些输出:

diag "Checking if Test::Exception::dies_ok will catch die in new";
dies_ok { My::SuperModule->new } "dies ok";
done_testing;

输出:

C:\...\t> prove my.pl
my.pl .. # Checking if Test::Exception::dies_ok will catch die in new
my.pl .. ok
All tests successful.
Files=1, Tests=1,  0 wallclock secs ( 0.05 usr +  0.02 sys =  0.06 CPU)
Result: PASS

与普通print语句相反,当diag等工具运行测试时,实际会显示prove输出。

答案 1 :(得分:3)

它对我有用。我需要做的就是:

  1. 注释掉测试没有使用的两个模块(Net :: Ping和Utils :: Variables :: Validator - 我没有安装它们。)
  2. 添加require作为模块的最后一行 - 因此它返回一个真值。
  3. 从测试中删除额外的use_okdone_testing;
  4. 在测试结束时添加了new File(classOf[YourClassName].getProtectionDomain.getCodeSource.getLocation.toURI.getPath) - 因此测试工具知道它已经到了测试结束。
  5. 您可能不关心该列表中的第一项,但如果您修复其他项目,它应该适合您。