代码之家  ›  专栏  ›  技术社区  ›  DigiLive

多次调用时,PHPUnit未完全覆盖PHP函数

  •  1
  • DigiLive  · 技术社区  · 9 年前

    或者更好的是,解释如何将其报告为完全覆盖?

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

    PHPUnit在调用一次时将线路报告为覆盖。

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

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

    2 回复  |  直到 9 年前
        1
  •  2
  •   Katie    9 年前

    我运行了您的代码并同意,这是一种奇怪的行为,最后显示了一个不存在的行 } 未覆盖(83%覆盖率)。我在中找到以下内容 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();
    }
    

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

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

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

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

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

    因此,我的最佳猜测是,数据提供程序函数在单元测试之前运行。

    编辑:

    添加了一些调试代码后,它确实得到了确认 全部的

    下面的例子产生了我的问题:

    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
    }