我发现的大多数Stackoverflow答案都是关于Perl构建过程的,单元测试和代码覆盖只是指向我的CPAN文档。指向CPAN模块绝对没有错,因为这是完整文档应该驻留的地方。但是,在很多情况下,我很难找到完整的工作代码示例。
我一直在互联网上搜索我可以下载或粘贴到我的IDE中的实际工作代码示例,就像典型的教程“Hello World”示例源代码一样,但是示例演示了单元的构建过程测试和代码覆盖率分析。有没有人有一个展示这些技术和流程的完整工作项目的小例子?
(我确实有一个小的工作示例,我会用它来回答我自己的问题,但可能还有其他SO用户有比我想出的更好的例子。)
答案 0 :(得分:102)
它花了我一段时间,它还让我从许多不同来源获取小片段并将它们融合在一起,但我想我有一个小的工作示例,足以向Perl新手演示Perl构建过程,包括单元测试和代码覆盖率分析&报告。 (我在Windows XP专业版PC上使用ActiveState ActivePerl v5.10.0,Module::Build,Test::More,Devel::Cover)
从Perl项目的目录开始,然后在项目目录下创建一个“lib”目录和一个“t”目录:
HelloPerlBuildWorld
|
|----------> lib
|
|----------> t
在“lib”目录中,创建名为“HelloPerlBuildWorld.pm”的文本文件。此文件是您将构建和测试的Perl模块。将以下内容粘贴到此文件中:
use strict;
use warnings;
package HelloPerlBuildWorld;
$HelloPerlBuildWorld::VERSION = '0.1';
sub hello {
return "Hello, Perl Build World!";
}
sub bye {
return "Goodbye, cruel world!";
}
sub repeat {
return 1;
}
sub argumentTest {
my ($booleanArg) = @_;
if (!defined($booleanArg)) {
return "null";
}
elsif ($booleanArg eq "false") {
return "false";
}
elsif ($booleanArg eq "true") {
return "true";
}
else {
return "unknown";
}
return "Unreachable code: cannot be covered";
}
1;
在“t”目录中,创建名为“HelloPerlBuildWorld.t”的文本文件。此文件是您的单元测试脚本,它将尝试完全测试上面的Perl模块。将以下内容粘贴到此文件中:
use strict;
use warnings;
use Test::More qw(no_plan);
# Verify module can be included via "use" pragma
BEGIN { use_ok('HelloPerlBuildWorld') };
# Verify module can be included via "require" pragma
require_ok( 'HelloPerlBuildWorld' );
# Test hello() routine using a regular expression
my $helloCall = HelloPerlBuildWorld::hello();
like($helloCall, qr/Hello, .*World/, "hello() RE test");
# Test hello_message() routine using a got/expected routine
is($helloCall, "Hello, Perl Build World!", "hello() IS test");
# Do not test bye() routine
# Test repeat() routine using a got/expected routine
for (my $ctr=1; $ctr<=10; $ctr++) {
my $repeatCall = HelloPerlBuildWorld::repeat();
is($repeatCall, 1, "repeat() IS test");
}
# Test argumentTest()
my $argumentTestCall1 = HelloPerlBuildWorld::argumentTest();
is($argumentTestCall1, "null", "argumentTest() IS null test");
# Test argumentTest("true")
my $argumentTestCall2 = HelloPerlBuildWorld::argumentTest("true");
is($argumentTestCall2, "true", "argumentTest() IS true test");
# Test argumentTest("false")
my $argumentTestCall3 = HelloPerlBuildWorld::argumentTest("false");
is($argumentTestCall3, "false", "argumentTest() IS false test");
# Test argumentTest(123)
my $argumentTestCall4 = HelloPerlBuildWorld::argumentTest(123);
is($argumentTestCall4, "unknown", "argumentTest() IS unknown test");
现在备份到顶级项目目录中,创建一个名为“Build.PL”的文本文件。此文件将创建您稍后将使用的构建脚本。将以下内容粘贴到此文件中:
use strict;
use warnings;
use Module::Build;
my $builder = Module::Build->new(
module_name => 'HelloPerlBuildWorld',
license => 'perl',
dist_abstract => 'HelloPerlBuildWorld short description',
dist_author => 'Author Name <email_addy@goes.here>',
build_requires => {
'Test::More' => '0.10',
},
);
$builder->create_build_script();
这就是你需要的所有文件。现在,从顶级项目目录的命令行中,键入以下命令:
perl Build.PL
您将看到类似于以下内容的内容:
Checking prerequisites...
Looks good
Creating new 'Build' script for 'HelloPerlBuildWorld' version '0.1'
现在您应该能够使用以下命令运行单元测试:
Build test
看到类似的内容:
Copying lib\HelloPerlBuildWorld.pm -> blib\lib\HelloPerlBuildWorld.pm
t\HelloPerlBuildWorld....ok
All tests successful.
Files=1, Tests=18, 0 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU)
要使用代码覆盖率分析运行单元测试,请尝试以下操作:
Build testcover
你会看到按顺序排列的东西:
t\HelloPerlBuildWorld....ok
All tests successful.
Files=1, Tests=18, 12 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU)
cover
Reading database from D:/Documents and Settings/LeuchKW/workspace/HelloPerlBuildWorld/cover_db
----------------------------------- ------ ------ ------ ------ ------ ------
File stmt bran cond sub time total
----------------------------------- ------ ------ ------ ------ ------ ------
D:/Perl/lib/ActivePerl/Config.pm 0.0 0.0 0.0 0.0 n/a 0.0
D:/Perl/lib/ActiveState/Path.pm 0.0 0.0 0.0 0.0 n/a 0.0
D:/Perl/lib/AutoLoader.pm 0.0 0.0 0.0 0.0 n/a 0.0
D:/Perl/lib/B.pm 18.6 16.7 13.3 19.2 96.4 17.6
...
[SNIP]
...
D:/Perl/lib/re.pm 0.0 0.0 0.0 0.0 n/a 0.0
D:/Perl/lib/strict.pm 84.6 50.0 50.0 100.0 0.0 73.1
D:/Perl/lib/vars.pm 44.4 36.4 0.0 100.0 0.0 36.2
D:/Perl/lib/warnings.pm 15.3 12.1 0.0 11.1 0.0 12.0
D:/Perl/lib/warnings/register.pm 0.0 0.0 n/a 0.0 n/a 0.0
blib/lib/HelloPerlBuildWorld.pm 87.5 100.0 n/a 83.3 0.0 89.3
Total 9.9 4.6 2.8 11.3 100.0 7.6
----------------------------------- ------ ------ ------ ------ ------ ------
Writing HTML output to D:/Documents and Settings/LeuchKW/workspace/HelloPerlBuildWorld/cover_db/coverage.html ...
done.
(有人请告诉我如何配置Cover以忽略所有Perl库除外,并在我写的单个文件上向我报告。我无法根据CPAN文档获得Cover过滤工作! )
现在,如果刷新顶级目录,则可以看到名为“cover_db”的新子目录。进入该目录并双击“coverage.html”文件,在您喜欢的Web浏览器中打开代码覆盖率报告。它为您提供了一个很好的彩色编码超文本报告,您可以在其中单击您的文件名,并在实际源代码旁边的报告中查看Perl模块的详细语句,分支,条件,子例程覆盖率统计信息。您可以在此报告中看到我们根本没有涵盖“bye()”例程,并且还有一行无法访问的代码,这些代码未按预期覆盖。
(来源:leucht.com)
在IDE中帮助自动执行此过程还有一件事是制作一些“Build.PL”类型文件,这些文件显式执行我们从命令行手动执行的一些构建目标。例如,我使用带有以下内容的“BuildTest.PL”文件:
use strict;
use warnings;
use Module::Build;
my $build = Module::Build->resume (
properties => {
config_dir => '_build',
},
);
$build->dispatch('build');
$build->dispatch('test');
然后我设置我的IDE来执行这个文件(通过“perl BuiltTest.PL”),只需单击一下鼠标,它就会自动从IDE运行我的单元测试代码,而不是从命令行手动执行。将“dispatch('test')”替换为“dispatch('testcover')”以执行自动代码覆盖。键入“构建帮助”以获取可从Module :: Build获得的构建目标的完整列表。
答案 1 :(得分:14)
作为对Kurt的回应,我建议使用他的BuiltTest.PL脚本替代。
use strict;
use warnings;
use Module::Build;
my $build = Module::Build->resume (
properties => {
config_dir => '_build',
},
);
$build->dispatch('build');
$build->dispatch('test');
它重用Build.PL构建的数据库(因此假定已经运行)。
答案 2 :(得分:12)
我在Intermediate Perl以及Mastering Perl中介绍了这一点。然而,库尔特给出了一个很好的总结。
我使用Module::Release将所有这些组合到一个发布脚本中。我键入一个命令,一切都发生了。
答案 3 :(得分:12)
非常有用的module-starter
生成一个易于使用的骨架项目,该项目处理模块安装,文档创建和模块文件的良好布局,以及 - 我认为 - 代码覆盖率支持。对于任何与Perl模块相关的努力,IMO都是一个很好的开端。
另外:使用与Module::Build
等CPAN相关的工具 - 即使对于可能永远不会公开发布的模块 - is a very good idea。
答案 4 :(得分:7)
(披露:我是作者)
如上所述对所有内容进行排序后,您可以采取下一步操作并使用Devel::CoverX::Covered进行排序。
有关具体命令行示例,请参阅synopsis。
在Devel::PerlySense中,Emacs支持在源代码缓冲区(screen shot)中显示覆盖率信息,并导航到/覆盖测试文件。