【问题标题】:PHPUnit HTML and Clover coverage reports differ due to codeCoverageIgnore由于 codeCoverageIgnore,PHPUnit HTML 和 Clover 覆盖率报告不同
【发布时间】:2011-08-04 21:56:22
【问题描述】:

我正在使用 PHPUnit 3.5.14 并且有一套测试覆盖了我的 PHP 应用程序的 100%,不包括带有 // @codeCoverageIgnore[Start|End] 的某些部分。 HTML 覆盖率报告显示 100% 的覆盖率。但是,当我生成一份 Clover XML 覆盖率报告(我希望 Jenkins 阅读该报告以强制执行 100% 覆盖率要求)时,它会将我忽略的所有代码都显示为未覆盖。

例如,我有一个包含 20 个方法的控制器类,其中一个看起来像这样:

// @codeCoverageIgnoreStart
/**
 * Gets an instance of Foo.  Abstracted for testing.
 *
 * @param array $options The constructor argument
 *
 * @return Foo
 */
protected function _getFoo(array $options)
{
    return new Foo($options);
}
// @codeCoverageIgnoreEnd

HTML 覆盖率报告显示了涵盖的 20 种方法,包括完全忽略的一种:

图片:报道摘录

http://i.imgur.com/VRtKR.png

但 Clover XML 报告显示涵盖了 19/20 种方法并且没有提及 _getFoo:

<class name="CampaignController" namespace="global" (...)>
  <metrics methods="20" coveredmethods="19" conditionals="0" coveredconditionals="0" statements="532" coveredstatements="532" elements="552" coveredelements="551"/>

...

  <line num="592" type="stmt" count="1"/>
  <line num="593" type="stmt" count="1"/>
  <line num="615" type="method" name="createAction" crap="2" count="2"/>
  <line num="617" type="stmt" count="2"/>

(顶部的 _getFoo 行是第 596-608 行。)

我的 PHPUnit 配置的日志记录部分如下所示:

<logging>
    <log type="coverage-html" target="../public/build/coverage" charset="UTF-8"
        yui="true" highlight="true" lowUpperBound="90" highLowerBound="100"/>
    <log type="coverage-clover" target="../public/build/test-coverage.xml"/>
</logging>

有没有办法配置 Clover 覆盖率日志条目,或者更改我的覆盖率忽略 cmets,以便 Clover 报告指示 100% 覆盖率以匹配 HTML 报告?

【问题讨论】:

    标签: unit-testing phpunit code-coverage clover


    【解决方案1】:

    问题出在PHP_CodeCoverage_Report_Clover::process()。虽然它在将方法中的行数相加时正确地忽略了标记的行,但它从不知道那些代码覆盖率 cmets 的 PHP_Token_Stream 获取方法列表。我在 github 创建了issue #54,应该比较容易修复。

    顺便说一句,阅读PHP_CodeCoverage_Report_Clover 使用的PHP_CodeCoverage::getLinesToBeIgnored(),您似乎可以通过将@codeCoverageIgnore 添加到其文档块来忽略整个类或方法。

    /**
     * Gets an instance of Foo.  Abstracted for testing.
     *
     * @param array $options The constructor argument
     * @return Foo
     *
     * @codeCoverageIgnore
     */
    

    虽然这不能解决问题,但它比使用匹配 // cmets 更容易。

    更新:如果您想尝试修复,请将foreach 中的方法替换为PHP_CodeCoverage_Report_Clover::process() 中的方法,并使用此修改后的版本。

    foreach ($_class['methods'] as $methodName => $method) {
        $methodCount        = 0;
        $methodLines        = 0;
        $methodLinesCovered = 0;
    
        for ($i  = $method['startLine'];
             $i <= $method['endLine'];
             $i++) {
            if (isset($ignoredLines[$i])) {
                continue;
            }
    
            $add   = TRUE;
            $count = 0;
    
            if (isset($files[$filename][$i])) {
                if ($files[$filename][$i] != -2) {
                    $classStatistics['statements']++;
                    $methodLines++;
                }
    
                if (is_array($files[$filename][$i])) {
                    $classStatistics['coveredStatements']++;
                    $methodLinesCovered++;
                    $count = count($files[$filename][$i]);
                }
    
                else if ($files[$filename][$i] == -2) {
                    $add = FALSE;
                }
            } else {
                $add = FALSE;
            }
    
            $methodCount = max($methodCount, $count);
    
            if ($add) {
                $lines[$i] = array(
                  'count' => $count,
                  'type'  => 'stmt'
                );
            }
        }
    
        if ($methodLines > 0) {
            $classStatistics['methods']++;
    
            if ($methodCount > 0) {
                $classStatistics['coveredMethods']++;
            }
    
            $lines[$method['startLine']] = array(
              'count' => $methodCount,
              'crap'  => PHP_CodeCoverage_Util::crap(
                           $method['ccn'],
                           PHP_CodeCoverage_Util::percent(
                             $methodLinesCovered,
                             $methodLines
                           )
                         ),
              'type'  => 'method',
              'name'  => $methodName
            );
        }
    }
    

    【讨论】:

    • 您的更改解决了我的问题,因为它为我提供了一份报告,表明 100% 的覆盖率并且应该允许我自动执行该要求。谢谢,并感谢 docblock 提示。但是您的更改给了我这个:&lt;metrics methods="19" coveredmethods="19" conditionals="0" coveredconditionals="0" statements="532" coveredstatements="532" elements="551" coveredelements="551"/&gt; 因此,它将忽略的代码视为不存在,而 HTML 报告将其视为已覆盖。可以说更有意义,但两者应该是一致的。
    • 我想我从来没有给予足够的关注。我希望 HTML 报告将忽略的行视为死代码,就像 cmets 一样。忽略代码意味着“我无法测试这个”而不是“我已经证明这个代码是正确的”。
    • 我同意。不确定塞巴斯蒂安对此事有何看法 - 我无法想象这个问题过去从未出现过。
    猜你喜欢
    • 2012-05-07
    • 2012-08-23
    • 1970-01-01
    • 2021-02-24
    • 2014-04-16
    • 2011-11-26
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    相关资源
    最近更新 更多