/vendor/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php
PHP | 388 lines | 253 code | 63 blank | 72 comment | 33 complexity | 8b778799a53befed71a00a58f985160d MD5 | raw file
- <?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\Util\TestDox;
- use const PHP_EOL;
- use function array_map;
- use function get_class;
- use function implode;
- use function method_exists;
- use function preg_split;
- use function trim;
- use PHPUnit\Framework\AssertionFailedError;
- use PHPUnit\Framework\Reorderable;
- use PHPUnit\Framework\Test;
- use PHPUnit\Framework\TestCase;
- use PHPUnit\Framework\TestResult;
- use PHPUnit\Framework\TestSuite;
- use PHPUnit\Framework\Warning;
- use PHPUnit\Runner\BaseTestRunner;
- use PHPUnit\Runner\PhptTestCase;
- use PHPUnit\TextUI\DefaultResultPrinter;
- use Throwable;
- /**
- * @internal This class is not covered by the backward compatibility promise for PHPUnit
- */
- class TestDoxPrinter extends DefaultResultPrinter
- {
- /**
- * @var NamePrettifier
- */
- protected $prettifier;
- /**
- * @var int The number of test results received from the TestRunner
- */
- protected $testIndex = 0;
- /**
- * @var int The number of test results already sent to the output
- */
- protected $testFlushIndex = 0;
- /**
- * @var array<int, array> Buffer for test results
- */
- protected $testResults = [];
- /**
- * @var array<string, int> Lookup table for testname to testResults[index]
- */
- protected $testNameResultIndex = [];
- /**
- * @var bool
- */
- protected $enableOutputBuffer = false;
- /**
- * @var array array<string>
- */
- protected $originalExecutionOrder = [];
- /**
- * @var int
- */
- protected $spinState = 0;
- /**
- * @var bool
- */
- protected $showProgress = true;
- /**
- * @param null|resource|string $out
- * @param int|string $numberOfColumns
- *
- * @throws \PHPUnit\Framework\Exception
- */
- public function __construct($out = null, bool $verbose = false, string $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false)
- {
- parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse);
- $this->prettifier = new NamePrettifier($this->colors);
- }
- public function setOriginalExecutionOrder(array $order): void
- {
- $this->originalExecutionOrder = $order;
- $this->enableOutputBuffer = !empty($order);
- }
- public function setShowProgressAnimation(bool $showProgress): void
- {
- $this->showProgress = $showProgress;
- }
- public function printResult(TestResult $result): void
- {
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function endTest(Test $test, float $time): void
- {
- if (!$test instanceof TestCase && !$test instanceof PhptTestCase && !$test instanceof TestSuite) {
- return;
- }
- if ($this->testHasPassed()) {
- $this->registerTestResult($test, null, BaseTestRunner::STATUS_PASSED, $time, false);
- }
- if ($test instanceof TestCase || $test instanceof PhptTestCase) {
- $this->testIndex++;
- }
- parent::endTest($test, $time);
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function addError(Test $test, Throwable $t, float $time): void
- {
- $this->registerTestResult($test, $t, BaseTestRunner::STATUS_ERROR, $time, true);
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function addWarning(Test $test, Warning $e, float $time): void
- {
- $this->registerTestResult($test, $e, BaseTestRunner::STATUS_WARNING, $time, true);
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function addFailure(Test $test, AssertionFailedError $e, float $time): void
- {
- $this->registerTestResult($test, $e, BaseTestRunner::STATUS_FAILURE, $time, true);
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function addIncompleteTest(Test $test, Throwable $t, float $time): void
- {
- $this->registerTestResult($test, $t, BaseTestRunner::STATUS_INCOMPLETE, $time, false);
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function addRiskyTest(Test $test, Throwable $t, float $time): void
- {
- $this->registerTestResult($test, $t, BaseTestRunner::STATUS_RISKY, $time, false);
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function addSkippedTest(Test $test, Throwable $t, float $time): void
- {
- $this->registerTestResult($test, $t, BaseTestRunner::STATUS_SKIPPED, $time, false);
- }
- public function writeProgress(string $progress): void
- {
- $this->flushOutputBuffer();
- }
- public function flush(): void
- {
- $this->flushOutputBuffer(true);
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- protected function registerTestResult(Test $test, ?Throwable $t, int $status, float $time, bool $verbose): void
- {
- $testName = $test instanceof Reorderable ? $test->sortId() : $test->getName();
- $result = [
- 'className' => $this->formatClassName($test),
- 'testName' => $testName,
- 'testMethod' => $this->formatTestName($test),
- 'message' => '',
- 'status' => $status,
- 'time' => $time,
- 'verbose' => $verbose,
- ];
- if ($t !== null) {
- $result['message'] = $this->formatTestResultMessage($t, $result);
- }
- $this->testResults[$this->testIndex] = $result;
- $this->testNameResultIndex[$testName] = $this->testIndex;
- }
- protected function formatTestName(Test $test): string
- {
- return method_exists($test, 'getName') ? $test->getName() : '';
- }
- protected function formatClassName(Test $test): string
- {
- return get_class($test);
- }
- protected function testHasPassed(): bool
- {
- if (!isset($this->testResults[$this->testIndex]['status'])) {
- return true;
- }
- if ($this->testResults[$this->testIndex]['status'] === BaseTestRunner::STATUS_PASSED) {
- return true;
- }
- return false;
- }
- protected function flushOutputBuffer(bool $forceFlush = false): void
- {
- if ($this->testFlushIndex === $this->testIndex) {
- return;
- }
- if ($this->testFlushIndex > 0) {
- if ($this->enableOutputBuffer &&
- isset($this->originalExecutionOrder[$this->testFlushIndex - 1])) {
- $prevResult = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex - 1]);
- } else {
- $prevResult = $this->testResults[$this->testFlushIndex - 1];
- }
- } else {
- $prevResult = $this->getEmptyTestResult();
- }
- if (!$this->enableOutputBuffer) {
- $this->writeTestResult($prevResult, $this->testResults[$this->testFlushIndex++]);
- } else {
- do {
- $flushed = false;
- if (!$forceFlush && isset($this->originalExecutionOrder[$this->testFlushIndex])) {
- $result = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex]);
- } else {
- // This test(name) cannot found in original execution order,
- // flush result to output stream right away
- $result = $this->testResults[$this->testFlushIndex];
- }
- if (!empty($result)) {
- $this->hideSpinner();
- $this->writeTestResult($prevResult, $result);
- $this->testFlushIndex++;
- $prevResult = $result;
- $flushed = true;
- } else {
- $this->showSpinner();
- }
- } while ($flushed && $this->testFlushIndex < $this->testIndex);
- }
- }
- protected function showSpinner(): void
- {
- if (!$this->showProgress) {
- return;
- }
- if ($this->spinState) {
- $this->undrawSpinner();
- }
- $this->spinState++;
- $this->drawSpinner();
- }
- protected function hideSpinner(): void
- {
- if (!$this->showProgress) {
- return;
- }
- if ($this->spinState) {
- $this->undrawSpinner();
- }
- $this->spinState = 0;
- }
- protected function drawSpinner(): void
- {
- // optional for CLI printers: show the user a 'buffering output' spinner
- }
- protected function undrawSpinner(): void
- {
- // remove the spinner from the current line
- }
- protected function writeTestResult(array $prevResult, array $result): void
- {
- }
- protected function getEmptyTestResult(): array
- {
- return [
- 'className' => '',
- 'testName' => '',
- 'message' => '',
- 'failed' => '',
- 'verbose' => '',
- ];
- }
- protected function getTestResultByName(?string $testName): array
- {
- if (isset($this->testNameResultIndex[$testName])) {
- return $this->testResults[$this->testNameResultIndex[$testName]];
- }
- return [];
- }
- protected function formatThrowable(Throwable $t, ?int $status = null): string
- {
- $message = trim(\PHPUnit\Framework\TestFailure::exceptionToString($t));
- if ($message) {
- $message .= PHP_EOL . PHP_EOL . $this->formatStacktrace($t);
- } else {
- $message = $this->formatStacktrace($t);
- }
- return $message;
- }
- protected function formatStacktrace(Throwable $t): string
- {
- return \PHPUnit\Util\Filter::getFilteredStacktrace($t);
- }
- protected function formatTestResultMessage(Throwable $t, array $result, string $prefix = '│'): string
- {
- $message = $this->formatThrowable($t, $result['status']);
- if ($message === '') {
- return '';
- }
- if (!($this->verbose || $result['verbose'])) {
- return '';
- }
- return $this->prefixLines($prefix, $message);
- }
- protected function prefixLines(string $prefix, string $message): string
- {
- $message = trim($message);
- return implode(
- PHP_EOL,
- array_map(
- static function (string $text) use ($prefix)
- {
- return ' ' . $prefix . ($text ? ' ' . $text : '');
- },
- preg_split('/\r\n|\r|\n/', $message)
- )
- );
- }
- }