我有一个问题,我创建了一个空项目来重现最小的情况,使其可重复 .
问题
具有未经测试的类的项目提供100%的覆盖率 . 有问题的方法是从其他地方间接调用的 not . 虽然在测试另一个类时间接调用了未测试类的其他方法 .
如何重现
步骤1:创建一个空的新symfony项目 .
- 我用这个命令创建了一个新的symfony 3.3项目:
symfony new coverage_trial_to_be_deleted
Result: 如果我运行 vendor/bin/simple-phpunit --coverage-html coverageReport
,我会按预期获得一个经过全面测试的项目,因为该示例包含一个默认控制器的默认测试 .
步骤2:删除控制器并创建两个命令,但不要覆盖它们 .
-
然后,我通过删除完整的
src/Controller
目录,控制器的测试以及应用程序配置中对该directroy的引用来消除控制器 . -
然后我用2个命令创建一个
src/Command
目录:DummyACommand.php
和DummyBCommand.php
. -
然后,我创建了一个愚蠢的测试,执行
assertTrue( true );
以报告某些内容,但根本不调用命令 .
Result: 这是正确的 . 然后在 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 );
仍在那里 .
Result: 现在,如果我查看DummyBCommand的覆盖范围,我应该看到覆盖了 configure()
方法,因为测试A的事实调用 $application->find( 'dummy:a' );
,我猜它会探索所有命令 .
我真的不太了解这一点,因为我只做 $application->add( new DummyACommand() );
并且我不知道 dummy:b
何时加载,但无论如何让我们给这个假设一个机会 .
所以我不介意看到绿色的 configure()
(下图中的注释 [1]
) .
但我不喜欢的是,然后,B的 execute()
而不是红色(没有人称之为执行,应该与第2步完全一样),它出现在白色中! :|像在注释 [2]
这里:
所以出于某种原因...测试命令A使PHPUnit改变了对命令B中“潜在可执行”的考虑,我不明白为什么 .
这使得整个项目被报告为100%测试,而它是错误的,如下所示:
但当然这些信息并不反映现实:命令B的 execute()
方法未被覆盖且从未执行过 .
我希望报告告诉我75%的线路覆盖率(4个中的3个)和50%的覆盖率(1个中的2个) .
所以......问题:
为什么PhpUnit在为A类添加测试时会改变对B类潜在可执行代码的考虑?
我怎样才能指示PhpUnit将B视为未被发现?
谢谢!哈维 .
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%(这是okey,因为它是我测试的那个)并且命令B在行中报告为50%,在类中报告为0%,因为我没有为它编写测试 . 方法
configure()
在内核引导和应用程序加载时运行:如果我们输入命令B(即:
DummyBCommand
),我们终于可以看到方法execute()
标记为红色,而不是白色:在此图像中,您可以在
[1]
中看到configure()
是100%而execute()
是0%,这是正确的 .在
[2]
中,您可以看到颜色 . 按预期,execute()
标记为红色 .最后,在
[3]
中,您可以看到XDebug版本是2.5.4
,是10 / sep / 2017上的最新稳定版(或者至少是更新向导建议我安装的版本) .所以...下载,配置,编译,安装和繁荣,完成!