Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1478d88

Browse files
committed
[PhpUnitBridge] Modernize CoverageListener
1 parent 4a053e5 commit 1478d88

File tree

4 files changed

+130
-206
lines changed

4 files changed

+130
-206
lines changed

src/Symfony/Bridge/PhpUnit/CoverageListener.php

Lines changed: 130 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,137 @@
1111

1212
namespace Symfony\Bridge\PhpUnit;
1313

14-
class_alias('Symfony\Bridge\PhpUnit\Legacy\CoverageListenerForV7', 'Symfony\Bridge\PhpUnit\CoverageListener');
14+
use PHPUnit\Framework\Test;
15+
use PHPUnit\Framework\TestCase;
16+
use PHPUnit\Framework\TestListener;
17+
use PHPUnit\Framework\TestListenerDefaultImplementation;
18+
use PHPUnit\Framework\Warning;
19+
use PHPUnit\Util\Annotation\Registry;
20+
use PHPUnit\Util\Test as TestUtil;
1521

16-
if (false) {
17-
class CoverageListener
22+
class CoverageListener implements TestListener
23+
{
24+
use TestListenerDefaultImplementation;
25+
26+
private $sutFqcnResolver;
27+
private $warningOnSutNotFound;
28+
private $warnings;
29+
30+
public function __construct(callable $sutFqcnResolver = null, bool $warningOnSutNotFound = false)
31+
{
32+
$this->sutFqcnResolver = $sutFqcnResolver;
33+
$this->warningOnSutNotFound = $warningOnSutNotFound;
34+
$this->warnings = [];
35+
}
36+
37+
public function startTest(Test $test): void
38+
{
39+
if (!$test instanceof TestCase) {
40+
return;
41+
}
42+
43+
$annotations = TestUtil::parseTestMethodAnnotations(\get_class($test), $test->getName(false));
44+
45+
$ignoredAnnotations = ['covers', 'coversDefaultClass', 'coversNothing'];
46+
47+
foreach ($ignoredAnnotations as $annotation) {
48+
if (isset($annotations['class'][$annotation]) || isset($annotations['method'][$annotation])) {
49+
return;
50+
}
51+
}
52+
53+
$sutFqcn = $this->findSutFqcn($test);
54+
if (!$sutFqcn) {
55+
if ($this->warningOnSutNotFound) {
56+
$test->getTestResultObject()->addWarning($test, new Warning('Could not find the tested class.'), 0);
57+
}
58+
59+
return;
60+
}
61+
62+
$covers = [$sutFqcn];
63+
while ($parent = get_parent_class($sutFqcn)) {
64+
$covers[] = $parent;
65+
$sutFqcn = $parent;
66+
}
67+
68+
if (class_exists(Registry::class)) {
69+
$this->addCoversForDocBlockInsideRegistry($test, $covers);
70+
71+
return;
72+
}
73+
74+
$this->addCoversForClassToAnnotationCache($test, $covers);
75+
}
76+
77+
private function addCoversForClassToAnnotationCache(Test $test, array $covers): void
78+
{
79+
$r = new \ReflectionProperty(TestUtil::class, 'annotationCache');
80+
$r->setAccessible(true);
81+
82+
$cache = $r->getValue();
83+
$cache = array_replace_recursive($cache, [
84+
\get_class($test) => [
85+
'covers' => $covers,
86+
],
87+
]);
88+
89+
$r->setValue(TestUtil::class, $cache);
90+
}
91+
92+
private function addCoversForDocBlockInsideRegistry(Test $test, array $covers): void
1893
{
94+
$docBlock = Registry::getInstance()->forClassName(\get_class($test));
95+
96+
$symbolAnnotations = new \ReflectionProperty($docBlock, 'symbolAnnotations');
97+
$symbolAnnotations->setAccessible(true);
98+
99+
// Exclude internal classes; PHPUnit 9.1+ is picky about tests covering, say, a \RuntimeException
100+
$covers = array_filter($covers, function (string $class) {
101+
$reflector = new \ReflectionClass($class);
102+
103+
return $reflector->isUserDefined();
104+
});
105+
106+
$symbolAnnotations->setValue($docBlock, array_replace($docBlock->symbolAnnotations(), [
107+
'covers' => $covers,
108+
]));
109+
}
110+
111+
private function findSutFqcn(Test $test): ?string
112+
{
113+
if ($this->sutFqcnResolver) {
114+
return ($this->sutFqcnResolver)($test);
115+
}
116+
117+
$class = \get_class($test);
118+
119+
$sutFqcn = str_replace('\\Tests\\', '\\', $class);
120+
$sutFqcn = preg_replace('{Test$}', '', $sutFqcn);
121+
122+
return class_exists($sutFqcn) ? $sutFqcn : null;
123+
}
124+
125+
public function __sleep()
126+
{
127+
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
128+
}
129+
130+
public function __wakeup()
131+
{
132+
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
133+
}
134+
135+
public function __destruct()
136+
{
137+
if (!$this->warnings) {
138+
return;
139+
}
140+
141+
echo "\n";
142+
143+
foreach ($this->warnings as $key => $warning) {
144+
echo sprintf("%d) %s\n", ++$key, $warning);
145+
}
19146
}
20147
}

src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerForV7.php

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php

Lines changed: 0 additions & 160 deletions
This file was deleted.

src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,4 @@
1212
require __DIR__.'/../src/BarCov.php';
1313
require __DIR__.'/../src/FooCov.php';
1414

15-
require __DIR__.'/../../../../Legacy/CoverageListenerTrait.php';
16-
require_once __DIR__.'/../../../../Legacy/CoverageListenerForV7.php';
1715
require __DIR__.'/../../../../CoverageListener.php';

0 commit comments

Comments
 (0)