草庐IT

PHPUnit 代码覆盖率显示 0%

coder 2024-04-28 原文

对于我的一个库 ( source ),我配置了 PHPunit 如下:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true">
    <testsuites>
        <testsuite name="PHPReboot Stopwatch Test Suite">
            <directory>tests/Phpreboot/Stopwatch</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory suffix=".php">src/Phpreboot/Stopwatch</directory>
        </whitelist>
    </filter>
    <logging>
        <log type="coverage-html" target="./log/codeCoverage" charset="UTF-8"
             yui="true" highlight="true"
             lowUpperBound="50" highLowerBound="80"/>
        <log type="testdox-html" target="./log/testdox.html" />
    </logging>
</phpunit>

在上面source , phpunit.xml.dist 被简单地复制为 phpunit.xml。

我的代码覆盖率报告正在生成,但报告显示代码覆盖率为 0%。然而,根据测试(检查源代码)我确定它必须超过 0%。

有人可以建议我的配置哪里出了问题吗?

第一条评论后编辑

测试用例:https://github.com/phpreboot/stopwatch/blob/master/tests/Phpreboot/Stopwatch/StopWatchTest.php

<?php

namespace Phpunit\Stopwatch;

use Phpreboot\Stopwatch\StopWatch;
use Phpreboot\Stopwatch\Timer;

/**
 * Class StopWatchTest
 * @package Phpunit\Stopwatch
 * @group Phpreboot
 * @group Phpreboot_Stopwatch
 * @group Phpreboot_Stopwatch_StopWatch
 */
class StopWatchTest extends \PHPUnit_Framework_TestCase
{
    /** @var  StopWatch $stopWatch */
    private $stopWatch;

    public function setUp()
    {
        $this->stopWatch = new StopWatch();
    }

    public function tearDown()
    {
        $this->stopWatch = null;
    }

    /* ******************/
    /* Constructor test */
    /* ******************/
    /**
     * @group Phpreboot_Stopwatch_StopWatch_constructor
     */
    public function testStopWatchHaveDefaultWatch()
    {
        /** @var Timer $defaultWatch */
        $defaultWatch = $this->stopWatch->getWatch();

        $this->assertNotNull($defaultWatch, "No watch available");
        $this->assertInstanceOf('Phpreboot\Stopwatch\Timer', $defaultWatch, "Not an instance of Watch");

        $name = $defaultWatch->getName();

        $this->assertEquals(StopWatch::STOPWATCH_DEFAULT_NAME, $name, "Default name of StopWatch is not set correctly");
    }

    /* ***************/
    /* addWatch Test */
    /* ***************/
    /**
     * @group Phpreboot_Stopwatch_StopWatch_addWatch
     */
    public function testWatchCanBeAdded()
    {
        $this->assertEquals(1, $this->stopWatch->getWatchCount(), "Stopwatch doesn't initialized with default watch.");

        $this->stopWatch->addWatch('testWatch');
        $this->assertEquals(2, $this->stopWatch->getWatchCount(), "Stopwatch could not be added");
    }

    /**
     * @group Phpreboot_Stopwatch_StopWatch_addWatch
     */
    public function testWatchCanNotBeAddedWithDuplicateName()
    {
        $this->assertEquals(1, $this->stopWatch->getWatchCount(), "Stopwatch doesn't initialized with default watch.");
        $this->assertFalse($this->stopWatch->addWatch(StopWatch::STOPWATCH_DEFAULT_NAME), "Watch with default name was duplicated.");
        $this->assertEquals(1, $this->stopWatch->getWatchCount(), "Watch with default name was duplicated.");

        $this->assertTrue($this->stopWatch->addWatch('testWatch'), "New watch couldn't be added.");
        $this->assertEquals(2, $this->stopWatch->getWatchCount(), "New watch couldn't be added.");
        $this->assertFalse($this->stopWatch->addWatch('testWatch'), "New watch with duplicate name was added.");
        $this->assertEquals(2, $this->stopWatch->getWatchCount(), "New watch with duplicate name was added.");
    }

    /* ********************/
    /* getWatchCount Test */
    /* ********************/
    /**
     * @group Phpreboot_Stopwatch_StopWatch_getWatchCount
     */
    public function testWatchCountIsCorrect()
    {
        $totalWatch = $this->stopWatch->getWatchCount();

        $this->assertEquals(1, $totalWatch, "Watch count is not correct");
    }

    /* ***************/
    /* getWatch Test */
    /* ***************/
    /**
     * @group Phpreboot_Stopwatch_StopWatch_getWatch
     */
    public function testDefaultWatchCouldBeReturned()
    {
        $watch = $this->stopWatch->getWatch();
        $this->assertInstanceOf('Phpreboot\Stopwatch\Timer', $watch, "Default watch is not an instance of Watch.");
        $this->assertEquals(StopWatch::STOPWATCH_DEFAULT_NAME, $watch->getName(), "Name of default was was not correctly set.");
    }

    /**
     * @group Phpreboot_Stopwatch_StopWatch_getWatch
     */
    public function testWatchCouldBeReturned()
    {
        $this->stopWatch->addWatch('newWatch');

        $newWatch = $this->stopWatch->getWatch("newWatch");
        $this->assertInstanceOf('Phpreboot\Stopwatch\Timer', $newWatch, "New watch is not an instance of Watch.");
    }
}

来源:https://github.com/phpreboot/stopwatch/blob/master/src/Phpreboot/Stopwatch/StopWatch.php

/*
 * This file is part of the PHPReboot/Stopwatch package.
 *
 * (c) Kapil Sharma <kapil@phpreboot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Phpreboot\Stopwatch;

use Phpreboot\Stopwatch\Timer;

class StopWatch
{
    const STOPWATCH_DEFAULT_NAME = "default_watch_R@nd0m_n@m3";

    private $timers;

    /**
     * Constructor to create new StopWatch instance with default watch.
     */
    public function __construct()
    {
        $this->timers = array();
        $this->addWatch(self::STOPWATCH_DEFAULT_NAME);
    }

    public function start($name = self::STOPWATCH_DEFAULT_NAME)
    {
        if (!$this->isWatchExist($name)) {
            return false;
        }

        return $this->getWatch($name)->start();
    }

    public function pause($name = self::STOPWATCH_DEFAULT_NAME)
    {
        if (!$this->isWatchExist($name)) {
            return false;
        }

        return $this->getWatch($name)->pause();
    }

    public function stop($name = self::STOPWATCH_DEFAULT_NAME)
    {
        if (!$this->isWatchExist($name)) {
            return false;
        }

        return $this->getWatch($name)->stop();
    }

    public function getTime($name = self::STOPWATCH_DEFAULT_NAME)
    {
        if (!$this->isWatchExist($name)) {
            return -1;
        }

        return $this->getWatch($name)->getTime();
    }

    public function isWatchExist($name)
    {
        return array_key_exists($name, $this->timers);
    }

    /**
     * Add a new watch to the StopWatch.
     *
     * @param string $name Name of watch to be added.
     * @return bool True if watch added successfully, false otherwise.
     */
    public function addWatch($name)
    {
        if (array_key_exists($name, $this->timers)) {
            return false;
        }

        $watch = new Timer($name);
        $this->timers[$name] = $watch;

        return true;
    }

    public function addWatches(array $watches)
    {
        $isWatchAdded = false;

        if (empty($watches)) {
            return $isWatchAdded;
        }

        foreach ($watches as $watch) {
            $this->addWatch($watch);
            $isWatchAdded = true;
        }

        return $isWatchAdded;
    }

    /**
     * Get a watch by name of watch.
     *
     * @param string $name Name of watch
     * @throws \InvalidArgumentException In case watch with name '$name' does not exist.
     * @return Timer A watch instance with name '$name'.
     */
    public function getWatch($name = self::STOPWATCH_DEFAULT_NAME)
    {
        if (!array_key_exists($name, $this->timers)) {
            throw new \InvalidArgumentException('Watch ' . $name . ' does not exist.');
        }

        return $this->timers[$name];
    }

    public function getWatchCount()
    {
        return count($this->timers);
    }
}

编辑 2:XDebug 设置

php --info | grep xdebug
/etc/php5/cli/conf.d/20-xdebug.ini,
xdebug
xdebug support => enabled
xdebug.auto_trace => Off => Off
xdebug.cli_color => 0 => 0
xdebug.collect_assignments => Off => Off
xdebug.collect_includes => On => On
xdebug.collect_params => 0 => 0
xdebug.collect_return => Off => Off
xdebug.collect_vars => Off => Off
xdebug.coverage_enable => On => On
xdebug.default_enable => On => On
xdebug.dump.COOKIE => no value => no value
xdebug.dump.ENV => no value => no value
xdebug.dump.FILES => no value => no value
xdebug.dump.GET => no value => no value
xdebug.dump.POST => no value => no value
xdebug.dump.REQUEST => no value => no value
xdebug.dump.SERVER => no value => no value
xdebug.dump.SESSION => no value => no value
xdebug.dump_globals => On => On
xdebug.dump_once => On => On
xdebug.dump_undefined => Off => Off
xdebug.extended_info => On => On
xdebug.file_link_format => no value => no value
xdebug.idekey => no value => no value
xdebug.max_nesting_level => 250 => 250
xdebug.overload_var_dump => On => On
xdebug.profiler_aggregate => Off => Off
xdebug.profiler_append => Off => Off
xdebug.profiler_enable => Off => Off
xdebug.profiler_enable_trigger => Off => Off
xdebug.profiler_output_dir => /tmp => /tmp
xdebug.profiler_output_name => cachegrind.out.%p => cachegrind.out.%p
xdebug.remote_autostart => Off => Off
xdebug.remote_connect_back => On => On
xdebug.remote_cookie_expire_time => 3600 => 3600
xdebug.remote_enable => On => On
xdebug.remote_handler => dbgp => dbgp
xdebug.remote_host => localhost => localhost
xdebug.remote_log => no value => no value
xdebug.remote_mode => req => req
xdebug.remote_port => 9000 => 9000
xdebug.scream => Off => Off
xdebug.show_exception_trace => Off => Off
xdebug.show_local_vars => Off => Off
xdebug.show_mem_delta => Off => Off
xdebug.trace_enable_trigger => Off => Off
xdebug.trace_format => 0 => 0
xdebug.trace_options => 0 => 0
xdebug.trace_output_dir => /tmp => /tmp
xdebug.trace_output_name => trace.%c => trace.%c
xdebug.var_display_max_children => 128 => 128
xdebug.var_display_max_data => 512 => 512
xdebug.var_display_max_depth => 3 => 3

最佳答案

@covers annotation 处每个测试的评论中告诉 PHPUnit 该测试涵盖了哪些代码。

The @covers annotation can be used in the test code to specify which method(s) a test method wants to test:

/**
 * @covers BankAccount::getBalance
 */
public function testBalanceIsInitiallyZero()
{
    $this->assertEquals(0, $this->ba->getBalance());
}

If provided, only the code coverage information for the specified method(s) will be considered.

此外,请确保您已安装 xdebug因为它是代码覆盖率报告工作所必需的。

关于PHPUnit 代码覆盖率显示 0%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32798415/

有关PHPUnit 代码覆盖率显示 0%的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  5. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  6. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  7. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  8. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  9. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  10. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

随机推荐