PHPUnit达到100%的代码覆盖率

2021/01/14 08:41 · php ·  · 0评论

我一直在为一个项目创建测试套件,尽管我意识到获得100%的覆盖率不是一个应该努力指标,但我还是希望代码覆盖率报告中有些奇怪的地方澄清。

看截图:

在此处输入图片说明

因为要测试的方法的最后一行是a return,所以最后一行(只是一个右括号)显示为从未执行,因此整个方法在概述中都标记为未执行。(或者,或者我没有正确阅读报告。)

完整的方法:

static public function &getDomain($domain = null) {
    $domain = $domain ?: self::domain();

    if (! array_key_exists($domain, self::$domains)) {
        self::$domains[$domain] = new Config();
    }

    return self::$domains[$domain];
}

这是有原因的还是小故障?

(是的,我通读了如何使用PHPUnit获得100%的代码覆盖率,尽管情况类似,但情况不同。)

编辑:

遍历该报告,我发现switch代码中其他地方声明也是如此因此,这种行为至少在某种程度上是一致的,但仍然令我感到困惑。

编辑2:

我正在运行:OS X上的PHPUnit 3.6.7,PHP 5.4.0RC5,XDebug 2.2.0-dev

第一关:100%的代码覆盖率是一个重要指标,以争取为。并非总是可以通过相同的努力来实现,并且这样做并不总是很重要:)

问题来自xDebug告诉PHPUnit此行是可执行的,但未涵盖。

在简单的情况下,xDebug会告诉您该行不可达,因此您可以获得100%的代码覆盖率。

请参阅下面简单示例


第二次更新

现在,此问题已解决,xDebug bugtracker因此构建新版本的xDebug将解决这些问题:)

更新(请参阅下面的php 5.3.x问题)

由于您运行的是PHP 5.4和xDebug的DEV版本,因此我已经安装了它们并对其进行了测试。我遇到了与您相同的问题,但您评论了相同的输出。

我不是100%确定问题是否来自php-code-coveragexDebug(phpunit模块)。xDebug开发人员也可能有问题。

我已经提交了一个错误,php-code-coverage我们将找出问题的根源。


对于PHP 5.3.x问题:

对于更复杂的情况下,这CAN失败。

对于您显示的代码,我只能说“它对我有用”(下面的复杂示例)。

也许更新xDebug和PHPUnit版本,然后重试。

我已经看到它在当前版本中失败,但是这有时取决于整个类的外观。

删除?:运算符和其他单行多语句的内容也可能会有所帮助。

据我所知,xDebug中正在进行重构,以避免更多此类情况。xDebug曾经希望能够提供“声明覆盖率”,这应该可以解决许多情况。目前没有什么可以做的

虽然//@codeCoverageIgnoreStart//@codeCoverageIgnoreEnd会“覆盖”这条线,但它看起来确实很丑陋,而且通常弊大于利。

对于发生这种情况的另一种情况,请参见以下问题和解答:

what-to-do-when-project-coding-standards-conflicts-with-unit-test-code-coverage


简单的例子:

<?php
class FooTest extends PHPUnit_Framework_TestCase {
    public function testBar() {
        $x = new Foo();
        $this->assertSame(1, $x->bar());
    }
}

<?php
class Foo {
    public function bar() {
        return 1;
    }
}

产生:

phpunit --coverage-text mep.php 
PHPUnit 3.6.7 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.50Mb

OK (1 test, 1 assertion)

Generating textual code coverage report, this may take a moment.

Code Coverage Report 
  2012-01-10 15:54:56

 Summary: 
  Classes: 100.00% (2/2)
  Methods: 100.00% (1/1)
  Lines:   100.00% (1/1)

Foo
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  1/  1)

复杂的例子:

<?php

require __DIR__ . '/foo.php';

class FooTest extends PHPUnit_Framework_TestCase {

    public function testBar() {
        $this->assertSame('b', Foo::getDomain('a'));
        $this->assertInstanceOf('Config', Foo::getDomain('foo'));
    }
}

<?php

class Foo {
    static $domains = array('a' => 'b');

    static public function &getDomain($domain = null) {
        $domain = $domain ?: self::domain();
        if (! array_key_exists($domain, self::$domains)) {
            self::$domains[$domain] = new Config();
        }
        return self::$domains[$domain];
    }
}

class Config {}

产生:

PHPUnit 3.6.7 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.50Mb

OK (1 test, 2 assertions)

Generating textual code coverage report, this may take a moment.

Code Coverage Report 
  2012-01-10 15:55:55

 Summary: 
  Classes: 100.00% (2/2)
  Methods: 100.00% (1/1)
  Lines:   100.00% (5/5)

Foo
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  5/  5)

这里的大部分问题是坚持要获得“行”的100%执行覆盖率。(经理喜欢这个想法;这是他们可以理解的简单模型)。许多行不是“可执行的”(空格,函数声明,注释,声明之间的间隙,“纯语法”,例如,开关或类声明的结束“}”,或跨多个源代码行的复杂语句)。

您真正想知道的是,“是否覆盖了所有可执行代码?” 这种区别似乎很愚蠢,但却导致解决方案。XDebug很好地按行号跟踪执行的内容,因此基于XDebug的方案将报告已执行行的范围。您会在此线程中遇到麻烦,包括笨拙的解决方案:必须在代码中加上“不要算我”注释,将“}”与最后一个可执行语句放在同一行,等等。愿意这样做,更不用说维护它了。

如果将可执行代码定义为可以被条件代码调用或由条件代码控制的代码(编译器人员称为“基本块”),并且以这种方式进行覆盖率跟踪,则代码的布局和愚蠢的情况简直消失了。这种类型的测试覆盖率工具会收集所谓的“分支覆盖率”,并且通过执行所有可执行代码,您实际上可以获取100%的“分支覆盖率”。此外,它还会处理一些有趣的情况,其中您在一行中有条件(使用“ x?y:z”),或者您在一行中有两个常规语句(例如,

 if  (...)  {   if  (...)  stmt1; else stmt2; stmt3 }

由于XDebug是按行跟踪的,因此我相信它将这视为一条陈述,并在控制到达该行时将其视为覆盖范围,而实际上有5个部分需要实际测试。

我们的PHP测试覆盖率工具实现了这些想法。特别是,它了解return语句后的代码不可执行,并且会告诉您尚未执行,如果它不是非空的。这使得OP的原始问题消失了。没有更多的玩游戏来获得“真实的”覆盖率。

与所有选择一样,有时也有不利之处。我们的工具具有仅在Windows下运行的代码工具组件。检测到的PHP代码可以在任何地方运行,并且处理/显示由独立于平台的Java程序完成。因此,这对于OP的OSX系统可能很尴尬。该工具可以在支持NFS的文件系统上正常工作,因此可以说可以在PC上运行该工具并对其OSX文件进行检测。

有人试图提高他的承保范围数而引起了这个特殊的问题。这个问题是恕我直言的人为问题,可以通过逐步解决问题来解决。还有另一种无需编写更多测试即可增加数量的方法,那就是查找并删除重复的代码。如果删除重复项,则只需较少的代码即可测试和测试一个(非)副本的效果,从而可以测试(现在不存在的另一个副本),因此更容易获得更大的数字。您可以在此处了解更多信息。

关于您的switch语句代码覆盖率问题,只需添加一个“默认”情况,该情况不做任何事情,您将获得完整的覆盖率。

这是使switch语句100%覆盖的方法:

确保至少有一个测试发送不存在的案例。

因此,如果您有:

switch ($name) {
    case 'terry':
        return 'blah';
    case 'lucky':
        return 'blahblah';
    case 'gerard':
        return 'blahblah';
}

确保至少有一个测试发送的名字既非terry也不luckygerard

本文地址:http://php.askforanswer.com/phpunitdadao100dedaimafugaishuai.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!