1

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

问题

具有未经测试的类的项目提供 100% 的覆盖率。有问题的方法不是从其他地方间接调用的。尽管在测试另一个类时会间接调用未测试类的其他方法。

如何重现

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

  • 我用这个命令创建了一个新的 symfony 3.3 项目:symfony new coverage_trial_to_be_deleted

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

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

  • 然后,我通过删除完整src/Controller目录、控制器测试以及应用程序配置中对该目录的引用来消除控制器。
  • src/Command然后我用 2 个命令创建一个目录:DummyACommand.phpDummyBCommand.php.
  • 然后我创建了一个愚蠢的测试,它执行一个assertTrue( true );有一些事情要报告,但根本不调用命令。

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

所有命令部分的结果

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

0% 时的命令

最后,如果我输入第二个命令,即“B”命令,例如DummyBCommand,我仍然可以看到既没有涵盖 theconfigure()execute()没有涵盖方法,并且正如预期的那样,我看到每个方法上都有一个红色区域:

B指挥部报告

到这里为止,一切都按预期工作。

第 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 的事实调用了 a$application->find( 'dummy:a' );并且我猜它探索了所有命令。

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

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

但我不喜欢的是,execute()B 的 不是以红色出现(没有人称该执行,应该完全像在步骤 2 中出现),而是以白色出现!!!:| 就像这里的注释[2]

现在命令 2 有一个白色部分而不是红色部分

所以出于某种原因......测试命令 A 使 PHPUnit 改变了它对命令 B 中“潜在可执行”的考虑,我不明白为什么。

这使得整个项目被报告为 100% 测试,虽然它是错误的,就像在这里:

完整报告显示错误的覆盖率指示

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

我希望报告能告诉我 75% 的线路覆盖率(4 个中的 3 个)和 50% 的类覆盖率(2 个中的 1 个)。

所以...问题:

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

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

谢谢!哈维。

4

1 回答 1

1

成立!!

快速解决方案

在此处更新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(我在那个线程中找到的链接),并xdebug按照说明编译了一个新的。

在这里您可以看到该项目现在不是 100%,而是 75% 的行和 50% 的类(如预期的那样):

在此处输入图像描述

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

在此处输入图像描述

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

在此处输入图像描述

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

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

最后,[3]您可以看到 XDebug 版本是2.5.42017 年 9 月 10 日的最新稳定版本(或者至少是更新向导建议我安装的版本)。

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

于 2017-09-10T15:12:26.350 回答