Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHPUnit code coverage show 0% coverage

For one of my library ( source ), I've configured PHPunit as follow:

<?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>

In above source, phpunit.xml.dist is simply copied as phpunit.xml.

My code coverage report is generating but reports shows 0% code coverage. However based on tests (check code in source) I'm sure it must be more than 0%.

Can someone please suggest where my configuration is going wrong?

Edit after first comment

Testcases: 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.");
    }
}

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

/*
 * This file is part of the PHPReboot/Stopwatch package.
 *
 * (c) Kapil Sharma <[email protected]>
 *
 * 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);
    }
}

Edit 2: XDebug settings

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
like image 407
Kapil Sharma Avatar asked Feb 08 '23 23:02

Kapil Sharma


2 Answers

In the comments for each test at the @covers annotation to tell PHPUnit what code is being covered in that test.

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.

Also, make sure you have installed xdebug as it is required for the code coverage report to work.

like image 112
John Conde Avatar answered Feb 11 '23 19:02

John Conde


I have a similar issue. In my case, I was sure the method was being tested cause the coverage report showed all lines green (meaning a test is running through them) but the summary displayed 0% for some methods, the only strange thing I have in my code was a deep nested array indented like this:

$array['key']
    ['foo']
    ['bar']
    ['fooz']
    ['bazz'] = "some_value";

after making it a single like it worked

$array['key']['foo']['bar']['fooz']['bazz'] = "some_value";

this was an strange issue with a strange walkaround

Hope it helps

like image 42
luxant Avatar answered Feb 11 '23 19:02

luxant