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 项目。
- 我用这个命令创建了一个新的 symfony 3.3 项目:
symfony new coverage_trial_to_be_deleted
结果: 如果我 运行 vendor/bin/simple-phpunit --coverage-html coverageReport
我得到一个完全测试的项目,正如预期的那样,因为示例包含一个默认控制器的默认测试.
第二步:删除控制器,创建两个命令,但不要覆盖它们。
- 然后我通过删除完整的
src/Controller
目录、控制器测试以及应用程序配置中对该目录的引用来消除控制器。
- 然后我用 2 个命令创建了一个
src/Command
目录:DummyACommand.php
和 DummyBCommand.php
。
- 然后我创建了一个愚蠢的测试,该测试执行
assertTrue( true );
以报告一些内容,但根本不调用命令。
结果: 这工作正常。然后它在 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(或者至少是更新的版本向导建议我安装)。
所以...下载、配置、编译、安装和繁荣,完成!
我有一个问题,我创建了一个空项目来重现使其可重复的最小情况。
问题
具有未经测试的 classes 的项目提供 100% 的覆盖率。有问题的方法是 而不是 从其他地方间接调用的。虽然在测试另一个class时间接调用了未测试class的其他方法。
如何重现
第 1 步:创建一个空的新 symfony 项目。
- 我用这个命令创建了一个新的 symfony 3.3 项目:
symfony new coverage_trial_to_be_deleted
结果: 如果我 运行 vendor/bin/simple-phpunit --coverage-html coverageReport
我得到一个完全测试的项目,正如预期的那样,因为示例包含一个默认控制器的默认测试.
第二步:删除控制器,创建两个命令,但不要覆盖它们。
- 然后我通过删除完整的
src/Controller
目录、控制器测试以及应用程序配置中对该目录的引用来消除控制器。 - 然后我用 2 个命令创建了一个
src/Command
目录:DummyACommand.php
和DummyBCommand.php
。 - 然后我创建了一个愚蠢的测试,该测试执行
assertTrue( true );
以报告一些内容,但根本不调用命令。
结果: 这工作正常。然后它在 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(或者至少是更新的版本向导建议我安装)。
所以...下载、配置、编译、安装和繁荣,完成!