我是Perl的新手,我想知道是否有首选的单元测试框架?
谷歌向我展示了一些不错的结果,但由于我是新手,我不知道社区内是否有明确的偏好。
答案 0 :(得分:37)
Perl有一套很棒的测试工具随附! Perl核心有几万个自动检查,并且大多数情况下它们都使用这些标准的Perl框架。他们都使用TAP绑定在一起 - Test Anything Protocol。
在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的answer中列出的所有优秀模块一起使用。事实上,因为Test::Builder - 构建Test::More
和其他人的工具(目前由Schwern维护...感谢Schwern!) - 如果需要,您可以构建自己的OWN测试子程序从头开始,将与所有其他测试框架一起使用。仅此一点就使Perl的TAP系统成为我认为最好的系统之一:一切都在一起工作,每个人都使用相同的工具,你可以通过很少的额外工作添加到框架中以满足您的需求。
答案 1 :(得分: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(通常从shell调用prove
)按顺序运行一系列测试,并获得已通过或失败的测试的摘要。
测试::更多也可以做一些更复杂的事情,比如标记测试为TODO(不要指望它们通过,但是以防万一)或SKIP(这些测试被破坏/可选,不要运行)他们)。您可以声明您希望运行的测试数量,因此如果您的测试脚本中途中断,则可以检测到这一点。
一旦开始进行更复杂的测试,您可能会发现其他一些CPAN模块很有用 - 这里有一些例子,但有很多(很多)更多:
Test::Exception - 测试您的代码是否抛出错误/不会抛出任何错误
Test::Warn - 测试您的代码是否/不会生成警告
Test::Deep - 深入比较对象。它们不必相同 - 您可以忽略数组排序,使用正则表达式,忽略对象类等
Test::Pod - 确保您的脚本有POD(文档),并且它是有效的
Test::Pod::Coverage - 确保您的POD记录模块中的所有方法/功能
Test::DBUnit - 测试数据库交互
Test::MockObject - 制作假装对象以控制测试环境
答案 2 :(得分:5)
绝对从这个页面开始:http://perldoc.perl.org/Test/Simple.html并按照Test::Tutorial的引用开始。
答案 3 :(得分:5)
如果您练习TDD,您会发现您的单元测试组正在改变很多。 Test::Class遵循xUnit模式(http://en.wikipedia.org/wiki/XUnit)。
对我来说,xUnit的主要好处是在方法中封装每个测试。框架通过测试方法的名称命名每个断言,并增加了在每次测试之前和之后运行setup-and teardown方法的可能性。
我已经尝试了“perl-ish”方式进行单元测试(仅使用Test :: More),但我发现它有点老式和繁琐。
答案 4 :(得分:3)
可能会有一些反建议:
反建议:
请勿使用Test::Unit
系列测试包用于Perl ,例如Test::Unit::Assert
和Test::Unit::TestCases
。
原因: Test::Unit
似乎已被放弃。
Test :: Unit,Test :: Unit :: TestCases,Test :: Unit :: Assert work,相当不错(当我使用它们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_object->is(VAL1,VAL2,TESTNAME)
,通常你可以使用Test :: Builder调用来解决像Test :: More这样构建在程序包之上的程序包的限制 - 就像修复错误所在的callstack级别一样报道。
Test :: Builder通常使用单例样式,但您可以创建多个对象。我不确定这些是否符合xUnit系列测试所期望的那样。
到目前为止,没有简单的方法来解决诸如Perl TAP测试之类的限制,使用TEST_NAMES,每个断言,没有层次结构,并且没有区分TEST_NAMES和TEST_ERROR_MESSAGES。 (错误的报告水平有助于弥补这一缺陷。)
有可能创建一个使Test :: Builder和TAP样式测试更加面向对象的适配器,这样你就可以对TAP以外的东西进行重新定义(记录比TAP更有用的信息 - 据说像ANT的XML协议) 。我认为调整名称和/或缺少的概念将涉及进入Test :: Builder或内省。