2010-05-20 59 views
28

我对Perl很陌生,我想知道是否有一个优选的单元测试框架?什么是Perl的首选单元测试框架?

谷歌正在向我展示了一些不错的成绩,但由于我是新来这个,我不知道是否有在社区内一个明显的偏好。

回答

35

Perl拥有一套强大的测试工具! Perl核心对其进行了数万次自动检查,并且大部分都使用这些标准的Perl框架。他们都使用TAP绑定在一起 - Test Anything Protocol

在Perl创建TAP测试使用Test::More家庭套餐,包括入门的标准方法。这里有一个简单的例子:

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就有了大量的其他功能,使测试其他事情变得更容易(字符串,正则表达式比较,深层结构比较),并且后端可以让你测试大型各个测试脚本组合在一起。

最重要的是,作为Schwern指出,几乎所有的现代Test::模块的协同工作。这意味着您可以使用Test::Class(如Markus指出)与rjhanswer中列出的所有优秀模块一起使用。实际上,因为Test::Builder - Test::More和其他构建的工具(现在由Schwern维护......感谢Schwern!) - 如果需要,您可以从头开始构建自己的测试子例程,它将与所有其他测试框架。这本身就使Perl的TAP系统的最好的一个赫然出现在我的意见:一切工作在一起,每个人都使用相同的工具,你可以添加到框架,以满足您的需求很少的额外工作。

+0

只是想知道什么是'tests => 3'。我需要硬编码的案件数量? – Mike 2010-05-20 17:45:02

+6

你不需要。但是如果你的测试脚本在输出1或2个测试结果后就死掉了,Test :: More就知道你的测试失败了(即使它出错的代码为0)。你也可以在脚本的末尾使用Test :: More'no_plan''或者调用'done_testing()'。 – rjh 2010-05-20 17:46:49

+0

我无法找到使用无计划的正确方法。如果我没有给'done_testing'指定一个数字参数,我会得到'你试图在没有计划的情况下运行测试!有一个计划' – Mike 2010-05-20 17:58:27

13

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(通常援引为prove从shell)运行的一系列序列测试,并获得其中的那些通过或失败的总结。

测试::更多也可以做一些更复杂的东西,如标记测试TODO(不要期望它们通过,但运行它们以防万一)或跳过(这些测试是打破/可选,不要运行它们)。您可以声明您希望运行的测试数量,因此如果您的测试脚本中途死亡,则可以检测到该数量。

一旦你开始做更复杂的测试,你可能会发现其他一些CPAN模块有用的 - 这里有几个ecamples,但也有许多(许多)更多:

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

5

如果你实践TDD,你会发现,你的单元测试集正在改变很多。 Test::Class遵循xUnit模式(http://en.wikipedia.org/wiki/XUnit)。

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

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

+1

我真的很喜欢Test :: Class。关于Test :: Class的简洁之处在于它只是构建基于TAP的测试的另一种方式 - 另一种框架,将其从“Procedural”转换为“面向对象”。它将“如何将其报告”从“如何运行”中分离出来,让您在Test :: Class对象中使用任何其他Test :: More样式测试步骤/测试函数。但它不一定是基于TAP的测试 - 它只是非常擅长。您可以扩展Test :: Class并覆盖很多默认行为,并简单地使用该框架。 – 2010-05-20 20:19:01

2

一些反建议可能是为了:

反建议:

不要使用Test::Unit家庭测试包的Perl的,如Test::Unit::AssertTest::Unit::TestCases

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

Test :: Unit,Test :: Unit :: TestCases,Test :: Unit :: Assert work,very well(when I used them 2015-2016)。 Test :: Unit被认为未与Perl的Test Anything Protocol(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)这样的特殊名称,而不是像$test_object->assert_equals(VAL1,VAL2,TEST_ERR_MSG)这样的xUnit样式名称。 Test :: Class具有自动检测注释的所有测试的令人愉快的功能:测试,与xUnit和TEST :: Unit :: TestCase使用内省运行所有名为test_ *的函数的方法相当。

但是,底层包Test::Builder是面向对象的,因此更多的xUnit风格。不要被这个名字吓倒 - 它不是工厂,它主要是一套测试断言方法。虽然大多数人都是从它那里继承的,但是如果你愿意的话,你可以直接打电话给他并且通常可以使用Test :: Builder调用来解决程序包(如Test :: Builder之上的Test :: More)的局限性 - 例如修复报告错误的callstack级别。

Test :: Builder通常使用singleton样式,但您可以创建多个对象。我不确定这些行为是否像一个xUnit家族测试期望的那样。

到目前为止,没有简单的方法可以解决Perl TAP测试等限制使用TEST_NAMES,每个断言,没有层次结构,也没有区分TEST_NAMES和TEST_ERROR_MESSAGES的限制。 (Err报告级别有助于减少缺陷)

可能会创建一个适配器,使Test :: Builder和TAP样式测试更面向对象,这样您就可以对TAP以外的其他事物进行重定位(记录更多比TAP更有用的信息 - 据说像ANT的XML协议)。我认为适应名称和/或缺少的概念将涉及进入Test :: Builder或反思。

+0

谢谢彼得。更干净。当我使用老化软件浪费时间时,我开始发泡。 – 2016-09-26 19:37:40