From 2f519261f57797c05fec1c307f04a6dc9a4a5650 Mon Sep 17 00:00:00 2001 From: Luke Downing Date: Wed, 8 Feb 2023 12:49:41 +0000 Subject: [PATCH] Fixes and improvements. --- bin/pest-wrapper.php | 41 +++-- composer.json | 2 +- docker/Dockerfile | 4 + src/Logging/TeamCity/Converter.php | 83 +--------- src/Plugins/Parallel.php | 11 +- .../Parallel/Paratest/ResultPrinter.php | 36 +---- .../Parallel/Paratest/WrapperRunner.php | 38 +++-- .../Parallel/Support/CompactPrinter.php | 146 ++++++------------ src/Support/StateGenerator.php | 102 ++++++++++++ 9 files changed, 227 insertions(+), 236 deletions(-) create mode 100644 src/Support/StateGenerator.php diff --git a/bin/pest-wrapper.php b/bin/pest-wrapper.php index 2d339284..210e7976 100644 --- a/bin/pest-wrapper.php +++ b/bin/pest-wrapper.php @@ -5,10 +5,36 @@ declare(strict_types=1); use ParaTest\WrapperRunner\ApplicationForWrapperWorker; use ParaTest\WrapperRunner\WrapperWorker; use Pest\ConfigLoader; +use Pest\Kernel; +use Pest\Plugins\Actions\CallsAddsOutput; +use Pest\Plugins\Actions\CallsHandleArguments; +use Pest\Support\Container; use Pest\TestSuite; use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\OutputInterface; -(static function (): void { +$bootPest = (static function (): void { + $argv = new ArgvInput(); + $rootPath = dirname(PHPUNIT_COMPOSER_INSTALL, 2); + $testSuite = TestSuite::getInstance( + $rootPath, + $argv->getParameterOption('--test-directory', (new ConfigLoader($rootPath))->getTestsDirectory()), + ); + + $output = new ConsoleOutput(OutputInterface::VERBOSITY_NORMAL, true); + + $container = Container::getInstance(); + $container->add(TestSuite::class, $testSuite); + $container->add(OutputInterface::class, $output); + $container->add(InputInterface::class, $argv); + $container->add(Container::class, $container); + + Kernel::boot(); +}); + +(static function () use ($bootPest): void { $getopt = getopt('', [ 'status-file:', 'progress-file:', @@ -50,16 +76,9 @@ use Symfony\Component\Console\Input\ArgvInput; $phpunitArgv = unserialize($getopt['phpunit-argv'], ['allowed_classes' => false]); assert(is_array($phpunitArgv)); - /** - * We need to instantiate the Pest Test suite instance - * so that Pest is able to execute correctly. - */ - $argv = new ArgvInput(); - $rootPath = dirname(PHPUNIT_COMPOSER_INSTALL, 2); - TestSuite::getInstance( - $rootPath, - $argv->getParameterOption('--test-directory', (new ConfigLoader($rootPath))->getTestsDirectory()), - ); + $bootPest(); + + (new CallsHandleArguments())($phpunitArgv); $application = new ApplicationForWrapperWorker( $phpunitArgv, diff --git a/composer.json b/composer.json index 0c4e5343..8c5342fe 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ ] }, "require-dev": { - "brianium/paratest": "^7.0", + "brianium/paratest": "^7.0.4", "pestphp/pest-dev-tools": "^2.4.0", "pestphp/pest-plugin-arch": "^2.0.0", "symfony/process": "^6.2.5" diff --git a/docker/Dockerfile b/docker/Dockerfile index 61334034..ff10bcb2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -12,6 +12,10 @@ RUN docker-php-ext-configure intl RUN docker-php-ext-install intl RUN docker-php-ext-enable intl +RUN apk add --no-cache $PHPIZE_DEPS linux-headers +RUN pecl install xdebug +RUN docker-php-ext-enable xdebug + COPY --from=composer:2 /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html diff --git a/src/Logging/TeamCity/Converter.php b/src/Logging/TeamCity/Converter.php index c0d91d41..0a1e592e 100644 --- a/src/Logging/TeamCity/Converter.php +++ b/src/Logging/TeamCity/Converter.php @@ -7,6 +7,7 @@ namespace Pest\Logging\TeamCity; use NunoMaduro\Collision\Adapters\Phpunit\State; use NunoMaduro\Collision\Adapters\Phpunit\TestResult; use Pest\Exceptions\ShouldNotHappen; +use Pest\Support\StateGenerator; use Pest\Support\Str; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Code\TestDox; @@ -28,12 +29,15 @@ final class Converter { private const PREFIX = 'P\\'; + private readonly StateGenerator $stateGenerator; + /** * Creates a new instance of the Converter. */ public function __construct( private readonly string $rootPath, ) { + $this->stateGenerator = new StateGenerator(); } /** @@ -183,83 +187,6 @@ final class Converter */ public function getStateFromResult(PhpUnitTestResult $result): State { - $state = new State(); - - foreach ($result->testErroredEvents() as $resultEvent) { - assert($resultEvent instanceof Errored); - $state->add(TestResult::fromTestCase( - $resultEvent->test(), - TestResult::FAIL, - $resultEvent->throwable() - )); - } - - foreach ($result->testFailedEvents() as $resultEvent) { - $state->add(TestResult::fromTestCase( - $resultEvent->test(), - TestResult::FAIL, - $resultEvent->throwable() - )); - } - - foreach ($result->testMarkedIncompleteEvents() as $resultEvent) { - $state->add(TestResult::fromTestCase( - $resultEvent->test(), - TestResult::INCOMPLETE, - $resultEvent->throwable() - )); - } - - foreach ($result->testConsideredRiskyEvents() as $riskyEvents) { - foreach ($riskyEvents as $riskyEvent) { - $state->add(TestResult::fromTestCase( - $riskyEvent->test(), - TestResult::RISKY, - Throwable::from(new IncompleteTestError($riskyEvent->message())) - )); - } - } - - foreach ($result->testSkippedEvents() as $resultEvent) { - if ($resultEvent->message() === '__TODO__') { - $state->add(TestResult::fromTestCase($resultEvent->test(), TestResult::TODO)); - - continue; - } - - $state->add(TestResult::fromTestCase( - $resultEvent->test(), - TestResult::SKIPPED, - Throwable::from(new SkippedWithMessageException($resultEvent->message())) - )); - } - - $numberOfPassedTests = $result->numberOfTests() - - $result->numberOfTestErroredEvents() - - $result->numberOfTestFailedEvents() - - $result->numberOfTestSkippedEvents() - - $result->numberOfTestsWithTestConsideredRiskyEvents() - - $result->numberOfTestMarkedIncompleteEvents(); - - for ($i = 0; $i < $numberOfPassedTests; $i++) { - $state->add(TestResult::fromTestCase( - - new TestMethod( - /** @phpstan-ignore-next-line */ - "$i", - /** @phpstan-ignore-next-line */ - '', - '', - 1, - /** @phpstan-ignore-next-line */ - TestDox::fromClassNameAndMethodName('', ''), - MetadataCollection::fromArray([]), - TestDataCollection::fromArray([]) - ), - TestResult::PASS - )); - } - - return $state; + return $this->stateGenerator->fromPhpUnitTestResult($result); } } diff --git a/src/Plugins/Parallel.php b/src/Plugins/Parallel.php index bc2df874..76e69b43 100644 --- a/src/Plugins/Parallel.php +++ b/src/Plugins/Parallel.php @@ -4,12 +4,14 @@ namespace Pest\Plugins; use ParaTest\ParaTestCommand; use Pest\Contracts\Plugins\HandlesArguments; +use Pest\Plugins\Actions\CallsAddsOutput; use Pest\Plugins\Concerns\HandleArguments; use Pest\Support\Arr; use Pest\Support\Container; use Pest\TestSuite; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\OutputInterface; +use function Pest\version; final class Parallel implements HandlesArguments { @@ -54,7 +56,14 @@ final class Parallel implements HandlesArguments $testSuite = TestSuite::getInstance(); - return ParaTestCommand::applicationFactory($testSuite->rootPath)->run(new ArgvInput($filteredArguments)); + $command = ParaTestCommand::applicationFactory($testSuite->rootPath); + $command->setAutoExit(false); + $command->setName('Pest'); + $command->setVersion(version()); + $exitCode = $command->run(new ArgvInput($filteredArguments)); + + $exitCode = (new CallsAddsOutput())($exitCode); + exit($exitCode); } private function markTestSuiteAsParallelSubProcessIfRequired(): void diff --git a/src/Plugins/Parallel/Paratest/ResultPrinter.php b/src/Plugins/Parallel/Paratest/ResultPrinter.php index 752b1787..7837ab36 100644 --- a/src/Plugins/Parallel/Paratest/ResultPrinter.php +++ b/src/Plugins/Parallel/Paratest/ResultPrinter.php @@ -5,28 +5,20 @@ declare(strict_types=1); namespace Pest\Plugins\Parallel\Paratest; use NunoMaduro\Collision\Adapters\Phpunit\TestResult as CollisionTestResult; -use NunoMaduro\Collision\Exceptions\TestException; use ParaTest\Options; use Pest\Plugins\Parallel\Support\CompactPrinter; -use PHPUnit\Runner\TestSuiteSorter; +use Pest\Support\StateGenerator; +use PHPUnit\Event\Test\Errored; use PHPUnit\TestRunner\TestResult\TestResult; -use PHPUnit\TextUI\Output\Default\ResultPrinter as DefaultResultPrinter; use PHPUnit\TextUI\Output\Printer; -use PHPUnit\TextUI\Output\SummaryPrinter; -use PHPUnit\Util\Color; -use SebastianBergmann\CodeCoverage\Driver\Selector; -use SebastianBergmann\CodeCoverage\Filter; use SebastianBergmann\Timer\Duration; -use SebastianBergmann\Timer\ResourceUsageFormatter; use SplFileInfo; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Output\OutputInterface; -use Termwind\Terminal; use function assert; use function fclose; use function feof; -use function floor; use function fopen; use function fread; use function fseek; @@ -34,26 +26,16 @@ use function ftell; use function fwrite; use function preg_replace; use function sprintf; -use function str_repeat; use function strlen; -use function Termwind\terminal; -use const DIRECTORY_SEPARATOR; -use const PHP_EOL; -use const PHP_VERSION; - /** @internal */ final class ResultPrinter { public readonly Printer $printer; private readonly CompactPrinter $compactPrinter; - private int $numTestsWidth = 0; - private int $maxColumn = 0; private int $totalCases = 0; - private int $column = 0; - private int $casesProcessed = 0; - private int $numberOfColumns = 80; + /** @var resource|null */ private $teamcityLogFileHandle; /** @var array */ @@ -98,7 +80,7 @@ final class ResultPrinter public function start(): void { $this->compactPrinter->line(sprintf( - 'Running %d test file%s using %d process%s', + 'Running %d test%s using %d process%s', $this->totalCases, $this->totalCases === 1 ? '' : 's', $this->options->processes, @@ -173,14 +155,10 @@ final class ResultPrinter $this->compactPrinter->newLine(); - $issues = array_map(fn($event) => CollisionTestResult::fromTestCase( - $event->test(), - CollisionTestResult::FAIL, - $event->throwable(), - ), [...$testResult->testFailedEvents(), ...$testResult->testErroredEvents()]); + $state = (new StateGenerator())->fromPhpUnitTestResult($testResult); - $this->compactPrinter->errors($issues); - $this->compactPrinter->recap($testResult, $duration); + $this->compactPrinter->errors($state); + $this->compactPrinter->recap($state, $testResult, $duration); } private function printFeedbackItem(string $item): void diff --git a/src/Plugins/Parallel/Paratest/WrapperRunner.php b/src/Plugins/Parallel/Paratest/WrapperRunner.php index 2644539f..1c0d87c8 100644 --- a/src/Plugins/Parallel/Paratest/WrapperRunner.php +++ b/src/Plugins/Parallel/Paratest/WrapperRunner.php @@ -16,6 +16,7 @@ use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Runner\CodeCoverage; use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; use PHPUnit\TestRunner\TestResult\TestResult; +use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; use PHPUnit\TextUI\ShellExitCodeCalculator; use PHPUnit\Util\ExcludeList; use SebastianBergmann\Timer\Timer; @@ -67,6 +68,8 @@ final class WrapperRunner implements RunnerInterface /** @var non-empty-string[] */ private readonly array $parameters; + private CodeCoverageFilterRegistry $codeCoverageFilterRegistry; + public function __construct( private readonly Options $options, private readonly OutputInterface $output @@ -92,6 +95,7 @@ final class WrapperRunner implements RunnerInterface $parameters[] = $wrapper; $this->parameters = $parameters; + $this->codeCoverageFilterRegistry = new CodeCoverageFilterRegistry(); } public function run(): int @@ -99,7 +103,7 @@ final class WrapperRunner implements RunnerInterface ExcludeList::addDirectory(dirname(__DIR__)); TestResultFacade::init(); EventFacade::seal(); - $suiteLoader = new SuiteLoader($this->options, $this->output); + $suiteLoader = new SuiteLoader($this->options, $this->output, $this->codeCoverageFilterRegistry,); $this->pending = $this->getTestFiles($suiteLoader); $result = TestResultFacade::result(); @@ -116,11 +120,6 @@ final class WrapperRunner implements RunnerInterface return $this->complete($result); } - public function getExitCode(): int - { - return $this->exitcode; - } - private function startWorkers(): void { for ($token = 1; $token <= $this->options->processes; ++$token) { @@ -155,6 +154,8 @@ final class WrapperRunner implements RunnerInterface ) { $this->pending = []; } elseif (($pending = array_shift($this->pending)) !== null) { + $this->debug(sprintf('Assigning %s to worker %d', $pending, $token)); + $worker->assign($pending); $this->batches[$token]++; } @@ -312,13 +313,14 @@ final class WrapperRunner implements RunnerInterface return; } - CodeCoverage::init($this->options->configuration); - $coverageMerger = new CoverageMerger(CodeCoverage::instance()); + $coverageManager = new CodeCoverage(); + $coverageManager->init($this->options->configuration, $this->codeCoverageFilterRegistry); + $coverageMerger = new CoverageMerger($coverageManager->codeCoverage()); foreach ($this->coverageFiles as $coverageFile) { $coverageMerger->addCoverageFromFile($coverageFile); } - CodeCoverage::generateReports( + $coverageManager->generateReports( $this->printer->printer, $this->options->configuration, ); @@ -349,14 +351,13 @@ final class WrapperRunner implements RunnerInterface } } + /** + * We are doing this because the SuiteLoader returns filenames incorrectly + * for Pest tests. Ideally we should find a cleaner solution. + */ private function getTestFiles(SuiteLoader $suiteLoader): array { - /** - * TODO: Clean this up - * - * We are doing this because the SuiteLoader returns filenames incorrectly - * for Pest tests. We need to find a better way to do this. - */ + $this->debug(sprintf("Found %d test file%s", count($suiteLoader->files), count($suiteLoader->files) === 1 ? '' : 's')); $tests = array_filter( $suiteLoader->files, @@ -365,4 +366,11 @@ final class WrapperRunner implements RunnerInterface return [...$tests, ...TestSuite::getInstance()->tests->getFilenames()]; } + + private function debug(string $message): void + { + if ($this->options->verbose) { + $this->output->writeln(" {$message} "); + } + } } diff --git a/src/Plugins/Parallel/Support/CompactPrinter.php b/src/Plugins/Parallel/Support/CompactPrinter.php index 1e852e5f..e32dff72 100644 --- a/src/Plugins/Parallel/Support/CompactPrinter.php +++ b/src/Plugins/Parallel/Support/CompactPrinter.php @@ -4,12 +4,26 @@ declare(strict_types=1); namespace Pest\Plugins\Parallel\Support; +use NunoMaduro\Collision\Adapters\Phpunit\Printers\DefaultPrinter; use NunoMaduro\Collision\Adapters\Phpunit\State; use NunoMaduro\Collision\Adapters\Phpunit\Style; use NunoMaduro\Collision\Adapters\Phpunit\TestResult; use NunoMaduro\Collision\Exceptions\ShouldNotHappen; +use Pest\Logging\TeamCity\Converter; +use Pest\Support\StateGenerator; +use PHPUnit\Event\Code\TestDox; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry\HRTime; +use PHPUnit\Event\Telemetry\Info; +use PHPUnit\Event\Telemetry\MemoryUsage; +use PHPUnit\Event\Telemetry\Snapshot; +use PHPUnit\Event\Test\Passed; +use PHPUnit\Event\TestData\TestDataCollection; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\IncompleteTestError; +use PHPUnit\Metadata\MetadataCollection; +use PHPUnit\TestRunner\TestResult\TestResult as PHPUnitTestResult; use ReflectionClass; use SebastianBergmann\Timer\Duration; use Symfony\Component\Console\Output\ConsoleOutput; @@ -49,22 +63,20 @@ final class CompactPrinter public function descriptionItem(string $item): void { - // TODO: Support todos + // TODO: Support TODOs - $icon = match (strtolower($item)) { - 'f', 'e' => '⨯', // FAILED - 's' => 's', // SKIPPED - 'w', 'r' => '!', // WARN, RISKY - 'i' => '…', // INCOMPLETE - '.' => '.', // PASSED - default => $item, - }; + $lookupTable = [ + '.' => ['gray', '.'], + 'S' => ['yellow', 's'], + 'I' => ['yellow', 'i'], + 'N' => ['yellow', 'i'], + 'R' => ['yellow', '!'], + 'W' => ['yellow', '!'], + 'E' => ['red', '⨯'], + 'F' => ['red', '⨯'], + ]; - $color = match (strtolower($item)) { - 'f', 'e' => 'red', - 'd', 's', 'i', 'r', 'w' => 'yellow', - default => 'gray', - }; + [$color, $icon] = $lookupTable[$item] ?? $lookupTable['.']; $symbolsOnCurrentLine = $this->compactProcessed % $this->compactSymbolsPerLine; @@ -80,102 +92,34 @@ final class CompactPrinter $this->output->write(sprintf('%s', $color, $icon)); $this->compactProcessed++; - - //switch ($item) { - // case self::TODO: - // return '↓'; - // case self::RUNS: - // return '•'; - // default: - // return '✓'; - //} } - public function errors(array $errors): void + public function errors(State $state): void { - array_map(function (TestResult $testResult): void { - if (! $testResult->throwable instanceof \PHPUnit\Event\Code\Throwable) { - throw new ShouldNotHappen(); - } - - renderUsing($this->output); - render(<<<'HTML' -
-
-
- HTML); - - $testCaseName = $testResult->testCaseName; - $description = $testResult->description; - - /** @var class-string $throwableClassName */ - $throwableClassName = $testResult->throwable->className(); - - $throwableClassName = ! in_array($throwableClassName, [ - ExpectationFailedException::class, - IncompleteTestError::class, - ], true) ? sprintf('%s', (new ReflectionClass($throwableClassName))->getShortName()) - : ''; - - $truncateClasses = $this->output->isVerbose() ? '' : 'flex-1 truncate'; - - renderUsing($this->output); - render(sprintf(<<<'HTML' -
- - %s %s>%s - - - %s - -
- HTML, $truncateClasses, $testResult->color, $testResult->type, $testCaseName, $description, $throwableClassName)); - - $this->style->writeError($testResult->throwable); - }, $errors); + $this->style->writeErrorsSummary($state, false); } - public function recap(\PHPUnit\TestRunner\TestResult\TestResult $testResult, Duration $duration): void + public function recap(State $state, PHPUnitTestResult $testResult, Duration $duration): void { - $testCounts = [ - 'passed' => ['green', $testResult->numberOfTestsRun()], - 'failed' => ['red', $testResult->numberOfTestFailedEvents()], - 'errored' => ['red', $testResult->numberOfTestErroredEvents()], - 'skipped' => ['yellow', $testResult->numberOfTestSkippedEvents()], - 'incomplete' => ['yellow', $testResult->numberOfTestMarkedIncompleteEvents()], - 'risky' => ['yellow', $testResult->numberOfTestsWithTestConsideredRiskyEvents()], - 'warnings' => ['yellow', $testResult->numberOfTestsWithTestTriggeredWarningEvents()], - ]; + assert($this->output instanceof ConsoleOutput); + $style = new Style($this->output); - $tests = []; + $nanoseconds = $duration->asNanoseconds() % 1000000000; + $snapshotDuration = HRTime::fromSecondsAndNanoseconds((int)$duration->asSeconds(), $nanoseconds); + $telemetryDuration = \PHPUnit\Event\Telemetry\Duration::fromSecondsAndNanoseconds((int)$duration->asSeconds(), $nanoseconds); - foreach ($testCounts as $type => [$color, $count]) { - if ($count === 0) { - continue; - } - - $tests[] = "$count $type"; - } - - $this->output->writeln(['']); - - if (! empty($tests)) { - $this->output->writeln([ - sprintf( - ' Tests: %s (%s assertions)', - implode(', ', $tests), - $testResult->numberOfAssertions() - ), - ]); - } - - $this->output->writeln([ - sprintf( - ' Duration: %ss', - number_format($duration->asSeconds(), 2, '.', '') + $telemetry = new Info( + new Snapshot( + $snapshotDuration, + MemoryUsage::fromBytes(0), + MemoryUsage::fromBytes(0), ), - ]); + $telemetryDuration, + MemoryUsage::fromBytes(0), + \PHPUnit\Event\Telemetry\Duration::fromSecondsAndNanoseconds(0, 0), + MemoryUsage::fromBytes(0), + ); - $this->output->writeln(''); + $style->writeRecap($state, $telemetry, $testResult); } } diff --git a/src/Support/StateGenerator.php b/src/Support/StateGenerator.php new file mode 100644 index 00000000..a78d499e --- /dev/null +++ b/src/Support/StateGenerator.php @@ -0,0 +1,102 @@ +testErroredEvents() as $testResultEvent) { + assert($testResultEvent instanceof Errored); + $state->add(\NunoMaduro\Collision\Adapters\Phpunit\TestResult::fromTestCase( + $testResultEvent->test(), + TestResult::FAIL, + $testResultEvent->throwable() + )); + } + + foreach ($testResult->testFailedEvents() as $testResultEvent) { + $state->add(TestResult::fromTestCase( + $testResultEvent->test(), + TestResult::FAIL, + $testResultEvent->throwable() + )); + } + + foreach ($testResult->testMarkedIncompleteEvents() as $testResultEvent) { + $state->add(TestResult::fromTestCase( + $testResultEvent->test(), + TestResult::INCOMPLETE, + $testResultEvent->throwable() + )); + } + + foreach ($testResult->testConsideredRiskyEvents() as $riskyEvents) { + foreach ($riskyEvents as $riskyEvent) { + $state->add(TestResult::fromTestCase( + $riskyEvent->test(), + TestResult::RISKY, + Throwable::from(new IncompleteTestError($riskyEvent->message())) + )); + } + } + + foreach ($testResult->testSkippedEvents() as $testResultEvent) { + if ($testResultEvent->message() === '__TODO__') { + $state->add(TestResult::fromTestCase($testResultEvent->test(), TestResult::TODO)); + + continue; + } + + $state->add(TestResult::fromTestCase( + $testResultEvent->test(), + TestResult::SKIPPED, + Throwable::from(new SkippedWithMessageException($testResultEvent->message())) + )); + } + + $numberOfPassedTests = $testResult->numberOfTestsRun() + - $testResult->numberOfTestErroredEvents() + - $testResult->numberOfTestFailedEvents() + - $testResult->numberOfTestSkippedEvents() + - $testResult->numberOfTestsWithTestConsideredRiskyEvents() + - $testResult->numberOfTestMarkedIncompleteEvents(); + + for ($i = 0; $i < $numberOfPassedTests; $i++) { + $state->add(TestResult::fromTestCase( + + new TestMethod( + /** @phpstan-ignore-next-line */ + "$i", + /** @phpstan-ignore-next-line */ + '', + '', + 1, + /** @phpstan-ignore-next-line */ + TestDox::fromClassNameAndMethodName('', ''), + MetadataCollection::fromArray([]), + TestDataCollection::fromArray([]) + ), + TestResult::PASS + )); + } + + return $state; + } +}