Code Monkey home page Code Monkey logo

Comments (13)

alebec avatar alebec commented on May 19, 2024 3

I found a way to use code coverage with Panter after inspecting selenium method.

It's a small hack and it can be improved but it work
you need to

  • patch public/index.php for saving usage of code (2 patches in this file)
  • overriding 'run()' method in all tests class to include code coverage usage at the end of each tests.
// public/index.php
// add method to start code coverage just in top of file 

require dirname(__DIR__).'/config/bootstrap.php';

// code coverage in tests
if($_SERVER['APP_ENV'] == 'test' ) {
    xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
}
// public/index.php
// add method to strop and srtore code coverage information at the end of /public/index.php

// code coverage in tests
if($_SERVER['APP_ENV'] == 'test' || 1) {
    // get code coverage information.
    $data = xdebug_get_code_coverage();
    xdebug_stop_code_coverage();

    $jsonCodeCoverageFile = __DIR__ . '/..'. DIRECTORY_SEPARATOR . 'var'. DIRECTORY_SEPARATOR. md5(uniqid(rand(), TRUE)).'.code_coverage';

    file_put_contents($jsonCodeCoverageFile, serialize($data));
}

Overriding each tests files

// tests/myFonctionnalTest.php

    public function run(TestResult $result = NULL)
    {

        if ($result === NULL) {
            $result = $this->createResult();
        }

        // run original method.
        parent::run($result);


        $it = new \RecursiveDirectoryIterator("var/");
        // Loop through files
        foreach(new \RecursiveIteratorIterator($it) as $file) {
            if ($file->getExtension() == 'code_coverage') {
                $content = file_get_contents($file);
                $content = unserialize($content);
                // append in current test result.
                $result->getCodeCoverage()->append(
                    $content, $this
                );
                // remove code_coverage_file
                unlink($file);
            }
        }

        return $result;
    }

Now we got covered code with Panther :)

code_coverage

from panther.

Dukecz avatar Dukecz commented on May 19, 2024 3

Version for Symfony 5.4:

Kernel.php:

<?php

namespace App;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use function file_put_contents;
use function is_dir;
use function md5;
use function mkdir;
use function mt_rand;
use function serialize;
use function uniqid;
use function xdebug_get_code_coverage;
use function xdebug_start_code_coverage;
use function xdebug_stop_code_coverage;

class Kernel extends BaseKernel
{
	public const COVERAGE_PANTHER_DIR = __DIR__ . '/../var/build/coverage-panther/';
	public const COVERAGE_PANTHER_ENV = 'panther';

	use MicroKernelTrait;

	/**
	 * @inheritDoc
	 */
	public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true)
	{
		// code coverage in tests
		if ($this->environment === $this::COVERAGE_PANTHER_ENV) {
			xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
		}

		$response = parent::handle($request, $type, $catch);

		if ($this->environment === $this::COVERAGE_PANTHER_ENV) {
			// get code coverage information.
			$data = xdebug_get_code_coverage();
			xdebug_stop_code_coverage();

			$jsonCodeCoverageFile = md5(uniqid((string) mt_rand(), true)) . '.code_coverage';

			if (!is_dir($this::COVERAGE_PANTHER_DIR)) {
				mkdir($this::COVERAGE_PANTHER_DIR, 0777, true);
			}

			file_put_contents($this::COVERAGE_PANTHER_DIR . $jsonCodeCoverageFile, serialize($data));
		}

		return $response;
	}
}

ExtendedPantherTestCase.php:
...

	/**
	 * @inheritDoc
	 */
	public function run(TestResult $result = null): TestResult
	{
		$result = parent::run($result);

		if (!is_dir(Kernel::COVERAGE_PANTHER_DIR)) {
			return $result;
		}

		$it = new \RecursiveDirectoryIterator(Kernel::COVERAGE_PANTHER_DIR);

		/** @var SplFileInfo $file */
		foreach (new \RecursiveIteratorIterator($it) as $file) {
			if ($file->getExtension() === 'code_coverage') {
				$content = file_get_contents($file->getRealPath());
				$content = unserialize($content);

				if (!empty($content)) {
					// append in current test result.
					$result->getCodeCoverage()->append(RawCodeCoverageData::fromXdebugWithoutPathCoverage($content), $this);
				}

				// remove code_coverage_file
				unlink($file->getRealPath());
			}
		}

		return $result;
	}

...

from panther.

petermanders89 avatar petermanders89 commented on May 19, 2024 1

I was running into this issue as well. The hack provided by alebec worked like a charm for me.
A small change I needed to make:

$content = file_get_contents($file->getRealPath());

unlink($file->getRealPath());

from panther.

AcelisWeaven avatar AcelisWeaven commented on May 19, 2024 1

Hi @alebec, thanks for the hack! Just wanted to add that if you're using PHP 7.3, you need to cast rand() as a string.

    $jsonCodeCoverageFile = __DIR__ . '/..'. DIRECTORY_SEPARATOR . 'var'. DIRECTORY_SEPARATOR. md5(uniqid((string)rand(), TRUE)).'.code_coverage';

The error was silently ignored and it took me hours to figure it out.

from panther.

dunglas avatar dunglas commented on May 19, 2024

As it browses the app through a web server, coverage will not work by default. It's probably possible to hack something, but it's not on my todo list for now.
I'll be glad to merge a PR anyway.

from panther.

dunglas avatar dunglas commented on May 19, 2024

Actually, it would be possible to use a hack similar to this one: https://github.com/api-platform/core/blob/master/features/bootstrap/CoverageContext.php

from panther.

baris1892 avatar baris1892 commented on May 19, 2024

I've tried the above, but I'm not really familiar with this kind of stuff

<?php

namespace App\Tests;

use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Filter;
use SebastianBergmann\CodeCoverage\Report\PHP;
use Symfony\Component\Panther\PantherTestCase;

class NewsControllerPantherTest extends PantherTestCase
{

    /** @var CodeCoverage */
    private static $coverage;

    protected function setup()
    {
        $filter = new Filter();
        $filter->addDirectoryToWhitelist(__DIR__ . '/../../src');
        self::$coverage = new CodeCoverage(null, $filter);
        self::$coverage->start("test1", true);
    }

    public function testJavaScript()
    {
        $client = static::createPantherClient();
        $crawler = $client->request('GET', '/');

        // do some asserts
        self::assertFalse(false);
    }

    protected function tearDown()
    {
        // what does this actually do?
         $feature = 'test';
        (new PHP())->process(self::$coverage, __DIR__ . "/../../build/cov/coverage-$feature.cov");

        self::$coverage->stop();
    }
}

So there will be created a coverage-test.cov, however PhpStorm does not show covered code. I'm not sure what is missing.

from panther.

dunglas avatar dunglas commented on May 19, 2024

If one of you guys can add it to the docs, it would be awesome!

from panther.

stof avatar stof commented on May 19, 2024

@alebec an improvement to your patch would be to put the code coverage in a dedicated subfolder of var to iterate only that folder when reading them (instead of iterating the full Symfony caches too)

from panther.

tidall87 avatar tidall87 commented on May 19, 2024

Hi, have you got some hack for symfony 5.3 and php 8?

from panther.

DigitalTimK avatar DigitalTimK commented on May 19, 2024

@Dukecz Thanks! This works great!

from panther.

Basster avatar Basster commented on May 19, 2024

Codeception has a very own router c3 for this task, maybe you can adopt something from it? I think it makes more sense than fiddeling around in the application kernel.

Additionally I'd prefer a kernel decorator, like the former CacheKernel, to decorate in a specific environment, only.

from panther.

vasilvestre avatar vasilvestre commented on May 19, 2024

Anyone tried to use pcov instead of xdebug ?

from panther.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.