如何在使用DBI的Perl模块中获得100%的测试覆盖率?

时间:2010-03-18 15:13:29

标签: perl testing code-coverage dbi

我对Devel :: Cover模块有点新,但发现它确保我没有错过测试非常有用。

我遇到的一个问题是了解Devel :: Cover的报告。我查看了文档,但无法弄清楚我需要测试什么来获得100%的覆盖率。

  

编辑 - 我应该说清楚我并不是说我需要100%的报道,   因为多人指出,   100%的报道是一个松散的术语   并不意味着我的代码没有bug,而且   可能并不总是完全的   必要。因为我是新来的   Devel ::封面,我很想知道    为什么 我的代码不是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 个答案:

答案 0 :(得分:10)

另外,不要过于担心100%的测试覆盖率。目标是完全测试您的应用程序,而不是在Devel :: Cover中获得完美的分数。请参阅Ovid关于该主题的帖子:

在你的情况下,看起来你没有覆盖所有分支,所以你没有得到完美的分数。你需要测试那些||的两侧。您获得的覆盖率为33%,因为您只能处理该行的三分之一的案例。来自Devel :: Cover的HTML报告显示了真值表以及您缺少的案例。

真值表显示了您必须为分支覆盖的可能状态。 1会向您显示一个为真的条件,0会向您显示错误的条件,X会向您显示您无法触及的条件。您必须测试可以执行的所有组合。由于||是一个短路运算符,一旦其中一个通过,就不必测试条件:

 0 || 1     connect to database fails and croak succeeds
 0 || 0     connect to database fails and croak fails (unlikely)
 1 || X     connect to database succeeds, so short circuit

这与您的特定问题有点无关,但我发现它经常出现在这些问题中。虽然Effective Perl Programming距离上架还有一个月,但Josh McAdams花了很多时间谈论Perl中的依赖注入。如果您在测试代码时遇到困难,通常会遇到设计问题。例如,如果您在子程序中内部生成数据库对象,那么您将自己画成一个角落。这就是为什么它可能很难测试。这可能不是你的问题,但需要考虑的事情。

答案 1 :(得分:5)

您必须模拟DBI库(或任何其他外部依赖项)才能完全覆盖您的单元测试。

您可以使用Test :: MockObject或任何其他模拟方法(例如我们公司开发了我们自己定制的非常强大的Perl模拟库)。

另请参阅this article专门针对DBI模拟。

此外,请确保您使用的是最新版本的Devel :: Cover。我曾经花了3天时间进行单元测试,直到我突然意识到这个错误不在我的代码中,而不是在我的单元测试中,而是在我的公司安装的旧版Devel :: Cover中。它实际上忽略了“A || B”情况下的某些代码路径。