繁体   English   中英

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

[英]What is the preferred unit testing framework for Perl?

我对 Perl 有点陌生,我想知道是否有首选的单元测试框架?

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

Perl 附带了大量出色的测试工具! Perl 核心对其进行了数以万计的自动检查,并且在大多数情况下,它们都使用这些标准 Perl 框架。 它们都使用 TAP(测试任何协议)联系在一起。

在 Perl 中创建 TAP 测试的标准方法是使用Test::More包系列,包括用于入门的Test::Simple 这是一个快速示例:

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::Harness后端可以让你测试大组单独的测试脚本。

最重要的是,正如Schwern指出的那样,几乎所有现代Test::模块都可以协同工作。 这意味着您可以将Test::Class (如Markus所指出的)与rjh答案中列出的所有优秀模块一起使用 事实上,因为Test::Builder —— Test::More和其他工具所基于的工具(目前由 Schwern 维护......感谢 Schwern!)——如果需要,您可以从将与所有其他测试框架一起工作。 仅此一点就使 Perl 的 TAP 系统成为我认为最好的系统之一:一切都可以协同工作,每个人都使用相同的工具,您只需很少的额外工作就可以添加到框架中以满足您的需求。

Perl 最流行的测试“框架”是一种称为 TAP(测试任何协议)的测试结果格式,它是一组如下所示的字符串:

ok 1 - Imported correctly
ok 2 - foo() takes two arguments
not ok 3 - foo() throws an error if passed no arguments

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

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

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');

您可以使用Test::Harness (通常从 shell 调用作为prove )按顺序运行一系列测试,并获得哪些测试通过或失败的摘要。

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

一旦您开始进行更复杂的测试,您可能会发现其他一些 CPAN 模块很有用——这里有几个例子,但还有很多(很多):

Test::Exception - 测试您的代码是否抛出错误/不抛出任何错误
Test::Warn - 测试您的代码是否生成警告
Test::Deep - 深入比较对象。 它们不必相同——您可以忽略数组排序、使用正则表达式、忽略对象类等。
Test::Pod - 确保你的脚本有 POD(文档),并且它是有效的
Test::Pod::Coverage - 确保您的 POD 记录了模块中的所有方法/功能
Test::DBUnit - 测试数据库交互
Test::MockObject - 制作假装对象来控制测试环境

绝对从这个页面开始: http : //perldoc.perl.org/Test/Simple.html并遵循Test::Tutorial的参考。

如果您练习 TDD,您会注意到您的单元测试集正在发生很多变化。 Test::Class遵循 xUnit 模式 ( http://en.wikipedia.org/wiki/XUnit )。

对我来说,xUnit 的主要好处是将每个测试封装在方法中。 该框架通过测试方法的名称命名每个断言,并增加了在每次测试前后运行设置和拆卸方法的可能性。

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

一些反建议可能是有序的:

反推荐:

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

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

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

但是 Test::Unit 令人沮丧,因为许多其他 Perl 测试包,主要是使用 Test::Builder 构建的,例如 Test::More、Test::Most、Test::Exception、Test::Differences、Test::Deep 、Test::Warn 等,不能与 Test::Unit 的面向对象测试方法很好地交互。

一旦您调整了 Test::Unit 以与 Test::More 和 TAP 一起工作,您就可以混合 Test::Unit 测试和 Test::Builder 测试; 但是这些其他软件包的良好功能不适用于 OO 扩展。 这也是使用 xUnit 风格测试的主要原因。

据说 CPAN 的Test::Class允许“以 xUnit/JUnit 风格轻松创建测试类”——但我不确定我是否可以推荐这个。 在我看来,它当然不像 xUnit - 不是 OO,像is(VAL1,VAL2,TESTNAME)这样的特殊名称is(VAL1,VAL2,TESTNAME)而不是像$test_object->assert_equals(VAL1,VAL2,TEST_ERR_MSG)这样的 xUnit 样式名称。 Test::Class 确实具有自动检测所有注释为:Test 的令人愉快的功能,类似于 xUnit 和 TEST::Unit::TestCase 使用自省运行所有名为 test_* 的函数的方法。

但是,底层包Test::Builder是面向对象的,因此更具有 xUnit 风格。 不要被这个名字吓跑——它不是一个工厂,它主要是一个带有测试断言方法的套件。 尽管大多数人继承自它,但您可以根据需要直接调用它,例如$test_object->is(VAL1,VAL2,TESTNAME) ,并且通常您可以使用 Test::Builder 调用来解决程序包(如 Test)的限制:: 更多建立在 Test::Builder 之上——比如修复报告错误的调用堆栈级别。

Test::Builder 通常使用单例样式,但您可以创建多个对象。 我不确定这些行为是否符合 xUnit 系列测试的预期。

到目前为止,没有简单的方法可以解决限制,例如 Perl TAP 测试使用 TEST_NAMES,每个断言,没有层次结构,并且不区分 TEST_NAMES 和 TEST_ERROR_MESSAGES。 (错误报告级别有助于弥补这一不足。)

可以创建一个适配器,使 Test::Builder 和 TAP 样式测试更加面向对象,以便您可以基于 TAP 以外的其他东西(它记录比 TAP 更有用的信息 - 据说像 ANT 的 XML 协议)。 我认为调整名称和/或缺少的概念将涉及进入 Test::Builder 或自省。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM