PhpUnit + Symfony:为什么覆盖率显示白色而不是红色,并且在未经测试的 class 上给出 100%?

PhpUnit + Symfony: Why coverage shows white instead of red and gives 100% on untested class?

我有一个问题,我创建了一个空项目来重现使其可重复的最小情况。

问题

具有未经测试的 classes 的项目提供 100% 的覆盖率。有问题的方法是 而不是 从其他地方间接调用的。虽然在测试另一个class时间接调用了未测试class的其他方法。

如何重现

第 1 步:创建一个空的新 symfony 项目。

结果: 如果我 运行 vendor/bin/simple-phpunit --coverage-html coverageReport 我得到一个完全测试的项目,正如预期的那样,因为示例包含一个默认控制器的默认测试.

第二步:删除控制器,创建两个命令,但不要覆盖它们。

结果: 这工作正常。然后它在 Command 目录上报告 0%,如下所示:

特别是在 Command 中我可以看到 2 个命令为 0%,这是正常的:

最后,如果我输入第二个命令,"B" 命令,比如 DummyBCommand,我仍然可以看到 configure()execute()方法已经涵盖,正如我所料,我看到每个方法都有一个红色区域:

至此,一切正常。

第 3 步:只为命令 A 添加测试,不测试命令 B。

然后我添加一个新测试,命名为DummyACommandTest.php,内容如下:

<?php

declare( strict_types=1 );

namespace Tests\AppBundle\Command;

use AppBundle\Command\DummyACommand;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

class EnvironmentListCommandTest extends KernelTestCase
{
    public function testExecute()
    {
        $kernel = $this->createKernel();
        $kernel->boot();

        $application = new Application( $kernel );
        $application->add( new DummyACommand() );

        $command = $application->find( 'dummy:a' );
        $commandTester = new CommandTester( $command );
        $commandTester->execute(
            [
                'command' => $command->getName(),
            ]
        );

        $output = $commandTester->getDisplay();
        $this->assertContains( 'dummy A command', $output );
    }
}

正如预期的那样,测试亮起绿灯,因为它调用 DummyACommand 并执行它,然后检查输出,它确实包含预期的内容:

它说 2 次测试,因为 assertTrue( true ); 仍然存在。

结果: 现在,如果我查看 DummyBCommand 的覆盖范围,我应该看到覆盖了 configure() 方法,因为测试 A 的事实调用了 $application->find( 'dummy:a' ); 我想它会探索所有命令。

我真的不太明白这个,因为我只做$application->add( new DummyACommand() );,我不知道什么时候加载dummy:b,但无论如何让我们给这个假设一个机会。

所以我不介意看到绿色的configure()(下图中的注释[1])。

但我不喜欢的是,B的execute()不是红色的(没有人调用那个执行,应该和步骤2完全一样),而是白色的!! ! :|就像这里的注释 [2]

所以出于某种原因...测试命令 A 使 PHPUnit 改变它对命令 B 中 "potentially executable" 的考虑,我不明白为什么。

这使得整个项目被报告为 100% 测试,而它是错误的,如下所示:

当然,这些信息并不能反映现实:命令 B 的 execute() 方法没有被覆盖,也从未被执行。

我希望报告告诉我 75% 的行覆盖率(4 个中的 3 个)和 50% class 的覆盖率(2 个中的 1 个)。

所以...问题:

为什么 PhpUnit 在为 class A 添加测试时改变了它对 class B 中潜在可执行代码的考虑?

如何指示 PhpUnit 将 B 视为未覆盖?

谢谢! 哈维

找到了!!

快速解决

在此处更新 xdebug 库:https://xdebug.org/wizard.php

详细解决方案

正如您在问题图片中看到的那样,我使用的是 Xdebug 2.4.0,因为那是我系统中的稳定 Ubuntu 16.04

根据此线程:https://github.com/sebastianbergmann/php-code-coverage/issues/411 在整整一年的时间里,这些人(谢谢大家)一直在追寻同样的问题:未报告为可执行的行。

最后他们得出的结论是 XDebug 中存在一个错误,最终被报告并更正了。

这是:xdebug 错误地向 phpunit 报告数据,因此 phpunit 运行宁基于错误的假设。

我在这里升级https://xdebug.org/wizard.php(我在那个帖子里找到的link),我按照说明编译了一个新的xdebug

在这里你可以看到项目现在不是 100%,而是 75% in lines 和 50% in classes(如预期):

在这里您可以看到命令 A 报告了 100%(这很好,因为它是我测试的)并且命令 B 报告了 50% 的行数和 0% 的 class,正如预期的那样,因为我没有为它编写测试。方法 configure() 在内核启动和应用程序加载时 运行:

如果我们输入命令 B(即:DummyBCommand),我们最终可以看到方法 execute() 被标记为红色,而不是白色:

在此图像中,您可以在 [1] 中看到 configure() 为 100%,execute() 为 0%,这是正确的。

[2]中您可以看到颜色。 execute() 正如预期的那样被标记为红色。

最后,在 [3] 中你可以看到 XDebug 版本是 2.5.4,最新的稳定版本是 10/sep/2017(或者至少是更新的版本向导建议我安装)。

所以...下载、配置、编译、安装和繁荣,完成!