Comments (13)
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 :)
from panther.
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.
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.
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.
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.
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.
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.
If one of you guys can add it to the docs, it would be awesome!
from panther.
@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.
Hi, have you got some hack for symfony 5.3 and php 8?
from panther.
@Dukecz Thanks! This works great!
from panther.
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.
Anyone tried to use pcov instead of xdebug ?
from panther.
Related Issues (20)
- createAdditionalPantherClient() with firefox driver not working. HOT 1
- No screenshot taken HOT 1
- TransportException
- Problem with detect driver HOT 3
- submit form isn't submitting
- How to use proxy with the firefox client? HOT 1
- Unable to run even a basic test HOT 2
- Can we add an option to not start a geckodriver listener?
- Not compatible with phpunit 10.4.0 HOT 6
- Failed to read marionette port error when using createFirefoxClient()
- Tag new release for Symfony 7 HOT 4
- <bootstrap> instead of <extension> expected in phpunit 10.4 configuration HOT 3
- TypeError is thrown when calling Crawler::html() HOT 1
- Error: Call to undefined method Symfony\Component\Panther\Client::assertSelectorIsNotVisible()
- Custom binary path to Firefox
- Chrome client crontab
- Selecting a radio button with value "0" is not possible if another element is pre-selected HOT 1
- Errors starting the webserver get hidden
- How to wait for all images to be loaded? HOT 2
- Docs improvement to help on how resize browser window
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from panther.