/
home
/
sjslayjy
/
public_html
/
sag_latest
/
vendor
/
phpunit
/
phpunit
/
src
/
Logging
/
TestDox
/
TestResult
/
Upload File
HOME
<?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use function array_keys; use function array_merge; use function assert; use function is_subclass_of; use function ksort; use function uksort; use function usort; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\Passed; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitErrorTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Framework\TestStatus\TestStatus; use PHPUnit\Logging\TestDox\TestResult as TestDoxTestMethod; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\SourceFilter; use ReflectionMethod; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestResultCollector { private readonly Source $source; /** * @psalm-var array<string, list<TestDoxTestMethod>> */ private array $tests = []; private ?TestStatus $status = null; private ?Throwable $throwable = null; private bool $prepared = false; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Facade $facade, Source $source) { $this->source = $source; $this->registerSubscribers($facade); } /** * @psalm-return array<string, TestResultCollection> */ public function testMethodsGroupedByClass(): array { $result = []; foreach ($this->tests as $prettifiedClassName => $tests) { $testsByDeclaringClass = []; foreach ($tests as $test) { $declaringClassName = (new ReflectionMethod($test->test()->className(), $test->test()->methodName()))->getDeclaringClass()->getName(); if (!isset($testsByDeclaringClass[$declaringClassName])) { $testsByDeclaringClass[$declaringClassName] = []; } $testsByDeclaringClass[$declaringClassName][] = $test; } foreach (array_keys($testsByDeclaringClass) as $declaringClassName) { usort( $testsByDeclaringClass[$declaringClassName], static function (TestDoxTestMethod $a, TestDoxTestMethod $b): int { return $a->test()->line() <=> $b->test()->line(); }, ); } uksort( $testsByDeclaringClass, /** * @psalm-param class-string $a * @psalm-param class-string $b */ static function (string $a, string $b): int { if (is_subclass_of($b, $a)) { return -1; } if (is_subclass_of($a, $b)) { return 1; } return 0; }, ); $tests = []; foreach ($testsByDeclaringClass as $_tests) { $tests = array_merge($tests, $_tests); } $result[$prettifiedClassName] = TestResultCollection::fromArray($tests); } ksort($result); return $result; } public function testPrepared(Prepared $event): void { if (!$event->test()->isTestMethod()) { return; } $this->status = TestStatus::unknown(); $this->throwable = null; $this->prepared = true; } public function testErrored(Errored $event): void { if (!$event->test()->isTestMethod()) { return; } $this->status = TestStatus::error($event->throwable()->message()); $this->throwable = $event->throwable(); if (!$this->prepared) { $test = $event->test(); assert($test instanceof TestMethod); $this->process($test); } } public function testFailed(Failed $event): void { if (!$event->test()->isTestMethod()) { return; } $this->status = TestStatus::failure($event->throwable()->message()); $this->throwable = $event->throwable(); } public function testPassed(Passed $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::success()); } public function testSkipped(Skipped $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::skipped($event->message())); } public function testMarkedIncomplete(MarkedIncomplete $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::incomplete($event->throwable()->message())); $this->throwable = $event->throwable(); } public function testConsideredRisky(ConsideredRisky $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::risky()); } public function testTriggeredDeprecation(DeprecationTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } if ($event->ignoredByTest()) { return; } if ($event->ignoredByBaseline()) { return; } if (!$this->source->ignoreSuppressionOfDeprecations() && $event->wasSuppressed()) { return; } if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredNotice(NoticeTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } if ($event->ignoredByBaseline()) { return; } if (!$this->source->ignoreSuppressionOfNotices() && $event->wasSuppressed()) { return; } if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $this->updateTestStatus(TestStatus::notice()); } public function testTriggeredWarning(WarningTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } if ($event->ignoredByBaseline()) { return; } if (!$this->source->ignoreSuppressionOfWarnings() && $event->wasSuppressed()) { return; } if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $this->updateTestStatus(TestStatus::warning()); } public function testTriggeredPhpDeprecation(PhpDeprecationTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } if ($event->ignoredByTest()) { return; } if ($event->ignoredByBaseline()) { return; } if (!$this->source->ignoreSuppressionOfPhpDeprecations() && $event->wasSuppressed()) { return; } if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredPhpNotice(PhpNoticeTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } if ($event->ignoredByBaseline()) { return; } if (!$this->source->ignoreSuppressionOfPhpNotices() && $event->wasSuppressed()) { return; } if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $this->updateTestStatus(TestStatus::notice()); } public function testTriggeredPhpWarning(PhpWarningTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } if ($event->ignoredByBaseline()) { return; } if (!$this->source->ignoreSuppressionOfPhpWarnings() && $event->wasSuppressed()) { return; } if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $this->updateTestStatus(TestStatus::warning()); } public function testTriggeredPhpunitDeprecation(PhpunitDeprecationTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredPhpunitError(PhpunitErrorTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::error()); } public function testTriggeredPhpunitWarning(PhpunitWarningTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::warning()); } /** * @throws InvalidArgumentException */ public function testFinished(Finished $event): void { if (!$event->test()->isTestMethod()) { return; } $test = $event->test(); assert($test instanceof TestMethod); $this->process($test); $this->status = null; $this->throwable = null; $this->prepared = false; } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerSubscribers(Facade $facade): void { $facade->registerSubscribers( new TestConsideredRiskySubscriber($this), new TestErroredSubscriber($this), new TestFailedSubscriber($this), new TestFinishedSubscriber($this), new TestMarkedIncompleteSubscriber($this), new TestPassedSubscriber($this), new TestPreparedSubscriber($this), new TestSkippedSubscriber($this), new TestTriggeredDeprecationSubscriber($this), new TestTriggeredNoticeSubscriber($this), new TestTriggeredPhpDeprecationSubscriber($this), new TestTriggeredPhpNoticeSubscriber($this), new TestTriggeredPhpunitDeprecationSubscriber($this), new TestTriggeredPhpunitErrorSubscriber($this), new TestTriggeredPhpunitWarningSubscriber($this), new TestTriggeredPhpWarningSubscriber($this), new TestTriggeredWarningSubscriber($this), ); } private function updateTestStatus(TestStatus $status): void { if ($this->status !== null && $this->status->isMoreImportantThan($status)) { return; } $this->status = $status; } private function process(TestMethod $test): void { if (!isset($this->tests[$test->testDox()->prettifiedClassName()])) { $this->tests[$test->testDox()->prettifiedClassName()] = []; } $this->tests[$test->testDox()->prettifiedClassName()][] = new TestDoxTestMethod( $test, $this->status, $this->throwable, ); } }