Viewing file: Converter.php (6.13 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
declare(strict_types=1);
namespace Pest\Logging;
use NunoMaduro\Collision\Adapters\Phpunit\State; use Pest\Exceptions\ShouldNotHappen; use Pest\Support\StateGenerator; use Pest\Support\Str; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\TestSuite\TestSuite; use PHPUnit\Framework\Exception as FrameworkException; use PHPUnit\TestRunner\TestResult\TestResult as PhpUnitTestResult;
/** * @internal */ 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; }
/** * Gets the test case method name. */ public function getTestCaseMethodName(Test $test): string { if (! $test instanceof TestMethod) { throw ShouldNotHappen::fromMessage('Not an instance of TestMethod'); }
return $test->testDox()->prettifiedMethodName(); }
/** * Gets the test case location. */ public function getTestCaseLocation(Test $test): string { if (! $test instanceof TestMethod) { throw ShouldNotHappen::fromMessage('Not an instance of TestMethod'); }
$path = $test->testDox()->prettifiedClassName(); $relativePath = $this->toRelativePath($path);
// TODO: Get the description without the dataset. $description = $test->testDox()->prettifiedMethodName();
return "$relativePath::$description"; }
/** * Gets the exception message. */ public function getExceptionMessage(Throwable $throwable): string { if (is_a($throwable->className(), FrameworkException::class, true)) { return $throwable->message(); }
$buffer = $throwable->className(); $throwableMessage = $throwable->message();
if ($throwableMessage !== '') { $buffer .= ": $throwableMessage"; }
return $buffer; }
/** * Gets the exception details. */ public function getExceptionDetails(Throwable $throwable): string { $buffer = $this->getStackTrace($throwable);
while ($throwable->hasPrevious()) { $throwable = $throwable->previous();
$buffer .= sprintf( "\nCaused by\n%s\n%s", $throwable->description(), $this->getStackTrace($throwable) ); }
return $buffer; }
/** * Gets the stack trace. */ public function getStackTrace(Throwable $throwable): string { $stackTrace = $throwable->stackTrace();
// Split stacktrace per frame. $frames = explode("\n", $stackTrace);
// Remove empty lines $frames = array_filter($frames);
// clean the paths of each frame. $frames = array_map( fn (string $frame): string => $this->toRelativePath($frame), $frames );
// Format stacktrace as `at <path>` $frames = array_map( fn (string $frame) => "at $frame", $frames );
return implode("\n", $frames); }
/** * Gets the test suite name. */ public function getTestSuiteName(TestSuite $testSuite): string { $name = $testSuite->name();
if (! str_starts_with($name, self::PREFIX)) { return $name; }
return Str::after($name, self::PREFIX); }
/** * Gets the trimmed test class name. */ public function getTrimmedTestClassName(TestMethod $test): string { return Str::after($test->className(), self::PREFIX); }
/** * Gets the test suite location. */ public function getTestSuiteLocation(TestSuite $testSuite): ?string { $tests = $testSuite->tests()->asArray();
// TODO: figure out how to get the file path without a test being there. if ($tests === []) { return null; }
$firstTest = $tests[0]; if (! $firstTest instanceof TestMethod) { throw ShouldNotHappen::fromMessage('Not an instance of TestMethod'); }
$path = $firstTest->testDox()->prettifiedClassName();
return $this->toRelativePath($path); }
/** * Gets the test suite size. */ public function getTestSuiteSize(TestSuite $testSuite): int { return $testSuite->count(); }
/** * Transforms the given path in relative path. */ private function toRelativePath(string $path): string { // Remove cwd from the path. return str_replace("$this->rootPath".DIRECTORY_SEPARATOR, '', $path); }
/** * Get the test result. */ public function getStateFromResult(PhpUnitTestResult $result): State { $events = [ ...$result->testErroredEvents(), ...$result->testFailedEvents(), ...$result->testSkippedEvents(), ...array_merge(...array_values($result->testConsideredRiskyEvents())), ...$result->testMarkedIncompleteEvents(), ];
$numberOfNotPassedTests = count( array_unique( array_map( function (BeforeFirstTestMethodErrored|Errored|Failed|Skipped|ConsideredRisky|MarkedIncomplete $event): string { if ($event instanceof BeforeFirstTestMethodErrored) { return $event->testClassName(); }
return $this->getTestCaseLocation($event->test()); }, $events ) ) );
$numberOfPassedTests = $result->numberOfTestsRun() - $numberOfNotPassedTests;
return $this->stateGenerator->fromPhpUnitTestResult($numberOfPassedTests, $result); } }
|