【问题标题】:PHP function not reported as completely covered by PHPUnit when calling multiple times多次调用时,PHP 函数未报告为完全被 PHPUnit 覆盖
【发布时间】:2017-02-10 03:52:44
【问题描述】:

有人能解释一下为什么下面的函数没有被 phpUnit 完全覆盖吗? 或者更好的是,解释如何将其报告为完全覆盖?

function itDoesThingsToValue()
{
    static $value = -1;
    if ($value < 0) {
        $value = 1978;
        //Do some more stuff with $value
        //But $value keeps being > 0
    }
    return $value;
}

当调用此函数一次或多次时,XDebug 代码覆盖率报告所有行被覆盖。

PHPUnit 在调用一次时报告行被覆盖。

多次调用它(由于不同的 PHPUnit 测试),PHPUnit 将 {} 之间的行报告为未覆盖。

由于静态变量 $value,我知道 {} 之间的行仅执行一次,但恕我直言,执行的行应始终报告为已覆盖,无论它们是否在后续调用中被跳过(通过以下测试)。

【问题讨论】:

    标签: php phpunit code-coverage


    【解决方案1】:

    我运行了您的代码并同意,这是一种奇怪的行为,在 last} 处显示一条不存在的行,因为没有被覆盖(83% 的覆盖率)。我在 Edge Cases 下的 PHPUnit documentation for Code Coverage 中找到了以下内容:

    // Because it is "line based" and not statement base coverage
    // one line will always have one coverage status
    if (false) this_function_call_shows_up_as_covered();
    
    // Due to how code coverage works internally these two lines are special.
    // This line will show up as non executable
    if (false)
        // This line will show up as covered because it is actually the 
        // coverage of the if statement in the line above that gets shown here!
        will_also_show_up_as_covered();
    
    // To avoid this it is necessary that braces are used
    if (false) {
        this_call_will_never_show_up_as_covered();
    }
    

    所以我将最后一个 } 移到了返回行,它开始报告 100% 的覆盖率。

    function itDoesThingsToValue(){
    static $value = -1;
    if ($value < 0) {
        $value = 1978;
        //Do some more stuff with $value
        //But $value keeps being > 0
    }
    return $value;}
    

    【讨论】:

    • 我已经看到了,但这与最后一行无关。 {} 之间的所有行都没有被覆盖。由于静态变量,它们仍然是第一次执行,当然不是连续执行。我的猜测是 PHPUnit 为每个测试启动和停止 xdebug 的代码覆盖,而不是从第一个测试开始并在最后一个测试之后停止。
    • 我明白了...我的配置是我打开了 xdebug(我可以逐步执行测试),只运行 PHPUnit 代码覆盖率,并且使用静态变量,我得到 100% 的覆盖率(甚至两个不同的单元测试分别调用它)。也许这可以帮助您隔离问题。
    • 感谢您对我的问题感兴趣。仅供参考...进一步的研究使我找到了我发布并标记为已接受的答案。
    【解决方案2】:

    我还不是很清楚,因为我不知道 PHPUnit 的来龙去脉,但事实就是这样……

    在第一次单元测试期间调用我的类的构造函数时调用该函数。在这个测试中,我声明该函数被覆盖(带有@covers 注释)。

    在更远的地方,我在数据提供程序中再次调用此函数以测试另一个函数。

    因为我认为我的函数已经过测试和覆盖(在构造函数测试中),所以应该保存它以便在数据提供程序中使用它。 实际上这会导致这些行被报告为未覆盖。

    所以我最好的猜测是 dataprovider 函数在单元测试之前运行。

    编辑:

    添加一些调试代码后,确实可以确认所有数据提供者方法在任何 test* 方法之前执行。

    以下示例产生了我的问题:

    public function setUp() {
        //Echo the executed testmethod name and 'starting' time into the console.
        echo $this->getName(), ' ', date('H:i:s'), chr(10), chr(13);
    }
    
    /**
    * @covers MyClass::_construct
    * @covers MyClass::myMethod
    */
    public function testConstructor() {
        //Do some stuff
    }
    
    public function myDataProvider() {
        //Echo the 'starting' time of the data provider method in the console.
        echo 'DataProvider started executing at', ' ', date(H:i:s), chr(10), chr(13);
        $value = MyClass::myMethod; //This causes the lines not being covered
        return [[$value + 1], [$value -1]];
    }
    
    /**
    * @covers MyClass::AnotherMethod
    * @dataprovider myDataProvider
    */
    public function testSomethingElse {
        //Do some stuff
    }
    

    控制台输出:

    Testing started at 21:55 ...
    DataProvider started executing at 21:55:46
    PHPUnit 5.5.5 by Sebastian Bergmann and contributors.
    
    testConstructor 21:55:47
    testSomethingElse 21:55:47
    

    我的解决办法是:

    private $testClassValue;
    
    /**
    * @covers MyClass::_construct
    * @covers MyClass::myMethod
    */
    public function testConstructor() {
        //Do some stuff
        $this->$testClassValue = myClass::value;
    }
    
    public function myDataProvider() {
        $value = $this->$testClassValue;
        return [[$value + 1], [$value -1]];
    }
    
    /**
    * @covers MyClass::AnotherMethod
    * @dataprovider myDataProvider
    */
    public function testSomethingElse {
        //Do some stuff
    }
    

    【讨论】:

      猜你喜欢
      • 2017-03-04
      • 2023-03-14
      • 2014-03-21
      • 2014-04-16
      • 1970-01-01
      • 1970-01-01
      • 2019-04-24
      • 2012-08-23
      • 2011-04-18
      相关资源
      最近更新 更多