如何在Perl中测试异常

大多数Perl程序员都熟悉Test::More;它是Perl中编写单元测试的首选库。但是Test::More不提供测试异常的函数。为此你需要Test::Exception。好的代码会抛出异常 - Paul Fenwick 曾经很好地总结了这种方法

bIlujDI' yIchegh()Qo'; yIHegh()!

It is better to die() than to return() in failure.

    -- Klingon programming proverb.

抛出异常最简单的方法是使用Perl的内置die函数。就像Test::More使得测试子程序返回正确的值变得容易一样,Test::Exception使得检查代码是否以正确的方式死亡变得容易(Test::Fatal是一个不错的选择)。

我的代码是否死亡了?

假设我们正在为以下包编写单元测试,该包导出double_integer子程序

package Double;
use Exporter;
@ISA = 'Exporter';
@EXPORT = 'double_integer';

sub double_integer
{
  my ($number) = @_;
  die 'double_integer() requires a positive integer as an argument'
    unless defined $number && $number =~ /^\d+$/;

  return $number * 2;
}

1;

除非以正整数调用double_integer子程序,否则此代码将die。我将此包保存为Double.pm。让我们为这个包编写一个测试脚本。Test::Exception导出dies_ok函数,该函数检查代码是否按预期死亡

use Test::Exception tests => 1;
use Double;

dies_ok { double_integer() } 'double_integer() dies with no number';

dies_ok很聪明,它实际上不会让您的代码死亡并退出程序,因为这会中断测试!相反,它会捕获任何抛出的异常,以便测试可以继续。我的程序也应该在以非数字作为参数调用double_integer时死亡。我可以为一些常见场景添加更多测试

use Test::Exception test => 6;
use Double;

dies_ok { double_integer() } 'double_integer() dies with no number';
dies_ok { double_integer(undef) } 'double_integer() dies with undef';
dies_ok { double_integer('abc') } 'double_integer() dies with text';
dies_ok { double_integer('1 two') } 'double_integer() dies with mixed';
dies_ok { double_integer('-7') } 'double_integer() dies with a negative';
dies_ok { double_integer('2.5') } 'double_integer() dies with a decimal';

我还可以使用throws_ok检查代码抛出了正确的异常

use Test::Exception tests => 1;
use Double;

throws_ok { double_integer() } qr/requires a positive integer/, 
  'double_integer() requires a positive integer';

throws_ok函数检查代码抛出了异常,而且还匹配正则表达式异常消息。如果您有几个可能抛出不同类型异常的不同条件,这很有用:想象一下在一个Web应用程序中,如果您想要在用户请求他们没有权限访问的页面(403)和请求一个不存在的页面(404)时抛出不同的异常代码。

Test::Exception与Test::More完全兼容,因此您可以在同一文件中组合两个库的函数

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

# test arg validation works
dies_ok { double_integer() } 'double_integer() dies with no number';
dies_ok { double_integer(undef) } 'double_integer() dies with undef';
dies_ok { double_integer('abc') } 'double_integer() dies with text';
dies_ok { double_integer('1 two') } 'double_integer() dies with mixed';
dies_ok { double_integer('-7') } 'double_integer() dies with a negative';
dies_ok { double_integer('2.5') } 'double_integer() dies with a decimal';

# test exception message
throws_ok { double_integer() } qr/requires a positive integer/, 
  'double_integer() requires a positive integer';

# test double_integer works
lives_ok { double_integer(1) } 'calling double() with a number lives';
is double_integer(0), 0, 'zero doubled is zero';
is double_integer(2), 4, 'two doubled is four';
is double_integer(999), 1998, 
  'nine nine nine doubled is one nine nine eight';

done_testing();

现在测试脚本检查了当参数不正确时函数是否抛出了适当的异常,并且当参数正确时返回参数的两倍。如果我把这个测试文件保存为Double.t,我就可以在终端运行测试

$ perl Double.t
ok 1 - double_integer() dies with no number
ok 2 - double_integer() dies with undef
ok 3 - double_integer() dies with text
ok 4 - double_integer() dies with mixed
ok 5 - double_integer() dies with a negative
ok 6 - double_integer() dies with a decimal
ok 7 - double_integer() requires a positive integer
ok 8 - calling double() with a number lives
ok 9 - zero doubled is zero
ok 10 - two doubled is four
ok 11 - nine nine nine doubled is one nine nine eight
1..11

所有测试都通过了。Test::Exception具有出色的文档,易于使用,所以请今天就把异常测试添加到您的代码中!

更新: 添加了Test::Fatal参考 2015-03-10


这篇文章最初发布在PerlTricks.com

标签

David Farrell

David是一位职业程序员,他经常推文博客关于代码和编程的艺术。

浏览他们的文章

反馈

这篇文章有什么问题吗?请通过在GitHub上打开问题或拉取请求来帮助我们。