我对Devel :: Cover模块有点新,但发现它确保我没有错过测试非常有用 .
我遇到的一个问题是了解Devel :: Cover的报告 . 我查看了文档,但无法弄清楚我需要测试什么才能获得100%的覆盖率 .
编辑 - 我应该说清楚我并不是说我需要100%的覆盖率,因为正如多人指出的那样,100%的覆盖率是一个松散的术语,并不意味着我的代码没有错误,并且可能并不总是完全没有必要 . 由于我是Devel :: Cover的新成员,我很想知道为什么我的代码不是100%覆盖,以防我错过了一些重要的测试 .
以下是封面报告的输出:
line err stmt bran cond sub pod time code
...
36 sub connect_database {
37 3 3 1 1126 my $self = shift;
38 3 100 24 if ( !$self->{dsn} ) {
39 1 7 croak 'dsn not supplied - cannot connect';
40 }
41 *** 2 33 21 $self->{dbh} = DBI->connect( $self->{dsn}, q{}, q{} )
42 || croak "$DBI::errstr";
43 1 11 return $self;
44 }
...
line err % l !l&&r !l&&!r expr
----- --- ------ ------ ------ ------ ----
41 *** 33 1 0 0 'DBI'->connect($$self{'dsn'}, '', '') || croak("$DBI::errstr")
以下是测试此特定行的代码示例:
my $database = MyModule::Database->new( { dsn => 'Invalid DSN' });
throws_ok( sub { $database->connect_database() },
qr/Can't connect to data source/,
'Test connection exception (invalid dsn)' );
此测试通过 - 连接确实抛出错误并完成我的“throws_ok”测试 .
我确实有一些测试可以测试成功的连接,这就是为什么我认为我有33%的覆盖率,但如果我正确阅读它,封面认为我没有测试语句的“|| croak”部分 . 我以为我是,通过“throws_ok”测试,但显然我错过了一些东西 .
有没有人有关于如何成功测试我的DBI->连接线的建议?
谢谢!
编辑:
brian向我发送了HTML报告和真相表,解释了为什么41号线没有通过 . 唯一的问题是我无法弄清楚它告诉我的是什么 . 我想我的问题的真正核心是为什么这条特定的线不能通过覆盖 .
这是真值表:
LINE # % # coverage # condition
41 # 33 # A | B | dec # 'DBI'->connect($$self{'dsn'}, '', '') || croak("$DBI::errstr")
# # 0 | 0 | 0 #
# # 0 | 1 | 1 #
# # 1 | X | 1 # (THIS LINE IS Green - the rest are red)
如果有人能帮助解释这个真相表,我会很感激 . 还有人提到要通过覆盖我需要有一个模拟数据库对象,但我不太清楚覆盖结果中的任何内容会让我知道这一点 .
再次感谢!
2 回答
此外,不要过于担心100%的测试覆盖率 . 目标是完全测试您的应用程序,而不是在Devel :: Cover中获得完美的分数 . 请参阅Ovid关于该主题的帖子:
More on 100% Test Coverage
100% Test Coverage?
在你的情况下,看起来你没有得到完美的分数 . 你需要测试那个练习
||
的两面 . 您获得的覆盖率为33%,因为您只能处理该行的三分之一的案例 . 来自Devel :: Cover的HTML报告显示了真值表以及您缺少的案例 .真值表显示了您必须覆盖分支的可能状态 .
1
向您显示的条件为真,0
显示您的条件为假,X
显示您无法触及的条件 . 您必须测试可以执行的所有组合 . 由于||
是一个短路运算符,因此只要其中一个通过,就不必测试条件:这与您的特定问题有点无关,但我发现它经常出现在这些问题中 . 虽然Effective Perl Programming已经过了一个月,但是Josh McAdams花了很多时间谈论Perl中的依赖注入 . 例如,如果您在子例程中内部生成数据库对象,那么您将自己画成一个角落 . 那个想要考虑的事情 .
您必须模拟DBI库(或任何其他外部依赖项)才能完全覆盖您的单元测试 .
您可以使用Test :: MockObject或任何其他模拟方法(例如,我们公司开发了我们自己定制的非常强大的Perl模拟库) .
另请参阅this article特别是关于DBI模拟 .
此外,请确保您使用的是最新版本的Devel :: Cover . 我曾经花了3天时间进行单元测试,直到我突然意识到这个错误不在我的代码中,而不是在我的单元测试中,而是在我的公司安装的旧版Devel :: Cover中 . 它实际上忽略了“A || B”情况下的某些代码路径 .