Perl的首选单元测试框架是什么?

Perl的首选单元测试框架是什么?,perl,unit-testing,Perl,Unit Testing,我对Perl有点陌生,我想知道是否有更喜欢的单元测试框架 Google向我展示了一些不错的结果,但由于我是新手,我不知道社区中是否有明确的偏好。一定要从这个页面开始:并遵循对的参考。Perl附带了大量很棒的测试工具!Perl核心有数万个自动检查,并且大部分都使用这些标准Perl框架。他们都是用水龙头绑在一起的 在Perl中创建TAP测试的标准方法是使用一系列包,包括入门包。下面是一个简单的例子: use 5.012; use warnings; use Test::More tests =&g

我对Perl有点陌生,我想知道是否有更喜欢的单元测试框架


Google向我展示了一些不错的结果,但由于我是新手,我不知道社区中是否有明确的偏好。

一定要从这个页面开始:并遵循对的参考。

Perl附带了大量很棒的测试工具!Perl核心有数万个自动检查,并且大部分都使用这些标准Perl框架。他们都是用水龙头绑在一起的

在Perl中创建TAP测试的标准方法是使用一系列包,包括入门包。下面是一个简单的例子:

use 5.012;
use warnings;

use Test::More tests => 3;

my $foo = 5;
my $bar = 6;

ok $foo == 5, 'Foo was assigned 5.';
ok $bar == 6, 'Bar was assigned 6.';
ok $foo + $bar == 11, 'Addition works correctly.';
其结果是:

ok 1 - Foo was assigned 5.
ok 2 - Bar was assigned 6.
ok 3 - Addition works correctly.
从本质上讲,要开始,您需要做的就是传递一个布尔值和一个解释应该发生什么的字符串

一旦您完成了这一步骤,Test::More就有了大量的其他函数,可以更轻松地测试其他东西(字符串、正则表达式比较、深层结构比较),还有一个后端,可以让您一起测试大量单独的测试脚本


除此之外,正如所指出的,几乎所有的现代
测试::
模块都协同工作。这意味着您可以使用(正如所指出的)中列出的所有优秀模块。事实上,因为--
Test::More
和其他工具是建立在上面的(目前由Schwern维护…谢谢Schwern!)--如果需要,您可以从头开始构建自己的测试子例程,它将与所有其他测试框架一起工作。仅此一点就让Perl的TAP系统在我看来成为了最好的系统之一:一切都在一起工作,每个人都使用相同的工具,您只需很少的额外工作就可以添加到框架上以满足您的需要。

Perl最流行的测试“框架”是一种称为TAP(test Anything Protocol)的测试结果格式这是一组字符串,看起来像:

ok 1 - Imported correctly
ok 2 - foo() takes two arguments
not ok 3 - foo() throws an error if passed no arguments
任何可以生成这些字符串的脚本都算作Perl测试。您可以使用为各种条件生成TAP-检查变量是否等于值,检查模块是否正确导入,或者两个结构(数组/哈希)是否相同。但是在真正的Perl精神中,有不止一种方法可以做到这一点,还有其他方法(例如,看起来有点像JUnit!)

测试脚本的一个简单示例(它们通常以
.t
结尾,例如
foo.t

您可以使用(通常在shell中调用为
prove
)按顺序运行一系列测试,并获得通过或失败测试的摘要

Test::More还可以做一些更复杂的事情,比如将测试标记为TODO(不要期望它们通过,但运行它们以防万一)或SKIP(这些测试是中断的/可选的,不要运行它们)。您可以声明希望运行的测试的数量,因此如果测试脚本中途停止,则可以检测到这一情况

一旦您开始进行更复杂的测试,您可能会发现其他一些CPAN模块很有用-以下是一些示例,但还有很多(很多)其他示例:

-测试您的代码是否抛出错误/不抛出任何错误
-测试您的代码是否生成警告
-深入比较对象。它们不必完全相同-您可以忽略数组顺序、使用正则表达式、忽略对象类等。
-确保您的脚本具有POD(文档),并且它是有效的
-确保POD记录模块中的所有方法/功能
-测试数据库交互

-使假装对象控制测试环境

如果您练习TDD,您会注意到您的单元测试集正在发生很大的变化。遵循xUnit模式()

对我来说,xUnit的主要好处是将每个测试封装在方法中。该框架使用测试方法的名称命名每个断言,并增加了在每个测试之前和之后运行setup和teardown方法的可能性


我也尝试过单元测试的“perl-ish”方法(仅使用Test::More),但我发现它有点过时和麻烦。

一些反对的建议可能是:

反建议:

不要使用Perl的
Test::Unit
测试包系列,例如
Test::Unit::Assert
Test::Unit::TestCases

原因:
Test::Unit
似乎已被放弃。

Test::Unit,Test::Unit::TestCases,Test::Unit::Assert工作得很好(当我在2015-2016年使用它们时)。单元应该没有与Perl的Test Anything协议(TAP)集成,尽管我发现这很容易修复

但是Test::Unit是令人沮丧的,因为其他很多Perl测试包,大部分是使用Test::Builder构建的,比如Test::More、Test::Most、Test::Exception、Test::Differences、Test::Deep、Test::Warn等,与Test::Unit的面向对象测试方法没有很好的交互

您可以将Test::Unit测试和Test::Builder测试混合在一起,只要您调整了Test::Unit以使用Test::More和TAP;但是这些其他包的良好特性对于OO扩展是不可用的。这也是使用xUnit风格测试的主要原因

据推测,CPAN的
Test::Class
允许“以xUnit/JUnit样式轻松创建测试类”——但我不确定是否可以推荐这样做。在我看来,它当然不像xUnit——不是OO,而是像
is(VAL1,VAL2,TESTNAME)
这样的特殊名称,而不是像
$test\u object->assert\u equals(VAL1,VAL2,test\u ERR\u MSG)
这样的xUnit风格的名称。Test::Class确实具有自动检测所有带注释的测试的令人愉快的特性:Test,与xUnit和Test::Unit::TestCase使用内省运行所有名为Test_*的函数的方法相当

但是,底层包Test::Builder是面向对象的,并且
use strict;
use warnings;
use Test::More tests => 3;  # Tell Test::More you intend to do 3 tests

my $foo = 3;
ok(defined $foo, 'foo is defined');
is($foo, 3, 'foo is 3');
$foo++;
is($foo, 4, 'incremented foo');