Вход Регистрация
Файл: vendor/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php
Строк: 309
<?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 PHPUnitUtilTestDox;

use const 
PHP_EOL;
use function 
array_map;
use function 
ceil;
use function 
count;
use function 
explode;
use function 
get_class;
use function 
implode;
use function 
preg_match;
use function 
sprintf;
use function 
strlen;
use function 
strpos;
use function 
trim;
use 
PHPUnitFrameworkTest;
use 
PHPUnitFrameworkTestCase;
use 
PHPUnitFrameworkTestResult;
use 
PHPUnitRunnerBaseTestRunner;
use 
PHPUnitRunnerPhptTestCase;
use 
PHPUnitUtilColor;
use 
SebastianBergmannTimerResourceUsageFormatter;
use 
SebastianBergmannTimerTimer;
use 
Throwable;

/**
 * @internal This class is not covered by the backward compatibility promise for PHPUnit
 */
class CliTestDoxPrinter extends TestDoxPrinter
{
    
/**
     * The default Testdox left margin for messages is a vertical line.
     */
    
private const PREFIX_SIMPLE = [
        
'default' => '│',
        
'start'   => '│',
        
'message' => '│',
        
'diff'    => '│',
        
'trace'   => '│',
        
'last'    => '│',
    ];

    
/**
     * Colored Testdox use box-drawing for a more textured map of the message.
     */
    
private const PREFIX_DECORATED = [
        
'default' => '│',
        
'start'   => '┐',
        
'message' => '├',
        
'diff'    => '┊',
        
'trace'   => '╵',
        
'last'    => '┴',
    ];

    private const 
SPINNER_ICONS = [
        
" e[36m◐e[0m running tests",
        
" e[36m◓e[0m running tests",
        
" e[36m◑e[0m running tests",
        
" e[36m◒e[0m running tests",
    ];

    private const 
STATUS_STYLES = [
        
BaseTestRunner::STATUS_PASSED => [
            
'symbol' => '✔',
            
'color'  => 'fg-green',
        ],
        
BaseTestRunner::STATUS_ERROR => [
            
'symbol'  => '✘',
            
'color'   => 'fg-yellow',
            
'message' => 'bg-yellow,fg-black',
        ],
        
BaseTestRunner::STATUS_FAILURE => [
            
'symbol'  => '✘',
            
'color'   => 'fg-red',
            
'message' => 'bg-red,fg-white',
        ],
        
BaseTestRunner::STATUS_SKIPPED => [
            
'symbol'  => '↩',
            
'color'   => 'fg-cyan',
            
'message' => 'fg-cyan',
        ],
        
BaseTestRunner::STATUS_RISKY => [
            
'symbol'  => '☢',
            
'color'   => 'fg-yellow',
            
'message' => 'fg-yellow',
        ],
        
BaseTestRunner::STATUS_INCOMPLETE => [
            
'symbol'  => '∅',
            
'color'   => 'fg-yellow',
            
'message' => 'fg-yellow',
        ],
        
BaseTestRunner::STATUS_WARNING => [
            
'symbol'  => '⚠',
            
'color'   => 'fg-yellow',
            
'message' => 'fg-yellow',
        ],
        
BaseTestRunner::STATUS_UNKNOWN => [
            
'symbol'  => '?',
            
'color'   => 'fg-blue',
            
'message' => 'fg-white,bg-blue',
        ],
    ];

    
/**
     * @var int[]
     */
    
private $nonSuccessfulTestResults = [];

    
/**
     * @var Timer
     */
    
private $timer;

    
/**
     * @param null|resource|string $out
     * @param int|string           $numberOfColumns
     *
     * @throws PHPUnitFrameworkException
     */
    
public function __construct($out nullbool $verbose falsestring $colors self::COLOR_DEFAULTbool $debug false$numberOfColumns 80bool $reverse false)
    {
        
parent::__construct($out$verbose$colors$debug$numberOfColumns$reverse);

        
$this->timer = new Timer;

        
$this->timer->start();
    }

    public function 
printResult(TestResult $result): void
    
{
        
$this->printHeader($result);

        
$this->printNonSuccessfulTestsSummary($result->count());

        
$this->printFooter($result);
    }

    protected function 
printHeader(TestResult $result): void
    
{
        
$this->write("n" . (new ResourceUsageFormatter)->resourceUsage($this->timer->stop()) . "nn");
    }

    protected function 
formatClassName(Test $test): string
    
{
        if (
$test instanceof TestCase) {
            return 
$this->prettifier->prettifyTestClass(get_class($test));
        }

        return 
get_class($test);
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     */
    
protected function registerTestResult(Test $test, ?Throwable $tint $statusfloat $timebool $verbose): void
    
{
        if (
$status !== BaseTestRunner::STATUS_PASSED) {
            
$this->nonSuccessfulTestResults[] = $this->testIndex;
        }

        
parent::registerTestResult($test$t$status$time$verbose);
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     */
    
protected function formatTestName(Test $test): string
    
{
        if (
$test instanceof TestCase) {
            return 
$this->prettifier->prettifyTestCase($test);
        }

        return 
parent::formatTestName($test);
    }

    protected function 
writeTestResult(array $prevResult, array $result): void
    
{
        
// spacer line for new suite headers and after verbose messages
        
if ($prevResult['testName'] !== '' &&
            (!empty(
$prevResult['message']) || $prevResult['className'] !== $result['className'])) {
            
$this->write(PHP_EOL);
        }

        
// suite header
        
if ($prevResult['className'] !== $result['className']) {
            
$this->write($this->colorizeTextBox('underlined'$result['className']) . PHP_EOL);
        }

        
// test result line
        
if ($this->colors && $result['className'] === PhptTestCase::class) {
            
$testName Color::colorizePath($result['testName'], $prevResult['testName'], true);
        } else {
            
$testName $result['testMethod'];
        }

        
$style self::STATUS_STYLES[$result['status']];
        
$line  sprintf(
            
' %s %s%s' PHP_EOL,
            
$this->colorizeTextBox($style['color'], $style['symbol']),
            
$testName,
            
$this->verbose ' ' $this->formatRuntime($result['time'], $style['color']) : ''
        
);

        
$this->write($line);

        
// additional information when verbose
        
$this->write($result['message']);
    }

    protected function 
formatThrowable(Throwable $t, ?int $status null): string
    
{
        return 
trim(PHPUnitFrameworkTestFailure::exceptionToString($t));
    }

    protected function 
colorizeMessageAndDiff(string $stylestring $buffer): array
    {
        
$lines      $buffer array_map('rtrim'explode(PHP_EOL$buffer)) : [];
        
$message    = [];
        
$diff       = [];
        
$insideDiff false;

        foreach (
$lines as $line) {
            if (
$line === '--- Expected') {
                
$insideDiff true;
            }

            if (!
$insideDiff) {
                
$message[] = $line;
            } else {
                if (
strpos($line'-') === 0) {
                    
$line Color::colorize('fg-red'Color::visualizeWhitespace($linetrue));
                } elseif (
strpos($line'+') === 0) {
                    
$line Color::colorize('fg-green'Color::visualizeWhitespace($linetrue));
                } elseif (
$line === '@@ @@') {
                    
$line Color::colorize('fg-cyan'$line);
                }
                
$diff[] = $line;
            }
        }
        
$diff implode(PHP_EOL$diff);

        if (!empty(
$message)) {
            
$message $this->colorizeTextBox($styleimplode(PHP_EOL$message));
        }

        return [
$message$diff];
    }

    protected function 
formatStacktrace(Throwable $t): string
    
{
        
$trace PHPUnitUtilFilter::getFilteredStacktrace($t);

        if (!
$this->colors) {
            return 
$trace;
        }

        
$lines    = [];
        
$prevPath '';

        foreach (
explode(PHP_EOL$trace) as $line) {
            if (
preg_match('/^(.*):(d+)$/'$line$matches)) {
                
$lines[] = Color::colorizePath($matches[1], $prevPath) .
                    
Color::dim(':') .
                    
Color::colorize('fg-blue'$matches[2]) .
                    
"n";
                
$prevPath $matches[1];
            } else {
                
$lines[]  = $line;
                
$prevPath '';
            }
        }

        return 
implode(''$lines);
    }

    protected function 
formatTestResultMessage(Throwable $t, array $result, ?string $prefix null): string
    
{
        
$message $this->formatThrowable($t$result['status']);
        
$diff    '';

        if (!(
$this->verbose || $result['verbose'])) {
            return 
'';
        }

        if (
$message && $this->colors) {
            
$style            self::STATUS_STYLES[$result['status']]['message'] ?? '';
            [
$message$diff] = $this->colorizeMessageAndDiff($style$message);
        }

        if (
$prefix === null || !$this->colors) {
            
$prefix self::PREFIX_SIMPLE;
        }

        if (
$this->colors) {
            
$color  self::STATUS_STYLES[$result['status']]['color'] ?? '';
            
$prefix array_map(static function ($p) use ($color)
            {
                return 
Color::colorize($color$p);
            }, 
self::PREFIX_DECORATED);
        }

        
$trace $this->formatStacktrace($t);
        
$out   $this->prefixLines($prefix['start'], PHP_EOL) . PHP_EOL;

        if (
$message) {
            
$out .= $this->prefixLines($prefix['message'], $message PHP_EOL) . PHP_EOL;
        }

        if (
$diff) {
            
$out .= $this->prefixLines($prefix['diff'], $diff PHP_EOL) . PHP_EOL;
        }

        if (
$trace) {
            if (
$message || $diff) {
                
$out .= $this->prefixLines($prefix['default'], PHP_EOL) . PHP_EOL;
            }
            
$out .= $this->prefixLines($prefix['trace'], $trace PHP_EOL) . PHP_EOL;
        }
        
$out .= $this->prefixLines($prefix['last'], PHP_EOL) . PHP_EOL;

        return 
$out;
    }

    protected function 
drawSpinner(): void
    
{
        if (
$this->colors) {
            
$id $this->spinState count(self::SPINNER_ICONS);
            
$this->write(self::SPINNER_ICONS[$id]);
        }
    }

    protected function 
undrawSpinner(): void
    
{
        if (
$this->colors) {
            
$id $this->spinState count(self::SPINNER_ICONS);
            
$this->write("e[1Ke[" strlen(self::SPINNER_ICONS[$id]) . 'D');
        }
    }

    private function 
formatRuntime(float $timestring $color ''): string
    
{
        if (!
$this->colors) {
            return 
sprintf('[%.2f ms]'$time 1000);
        }

        if (
$time 1) {
            
$color 'fg-magenta';
        }

        return 
Color::colorize($color' ' . (int) ceil($time 1000) . ' ' Color::dim('ms'));
    }

    private function 
printNonSuccessfulTestsSummary(int $numberOfExecutedTests): void
    
{
        if (empty(
$this->nonSuccessfulTestResults)) {
            return;
        }

        if ((
count($this->nonSuccessfulTestResults) / $numberOfExecutedTests) >= 0.7) {
            return;
        }

        
$this->write("Summary of non-successful tests:nn");

        
$prevResult $this->getEmptyTestResult();

        foreach (
$this->nonSuccessfulTestResults as $testIndex) {
            
$result $this->testResults[$testIndex];
            
$this->writeTestResult($prevResult$result);
            
$prevResult $result;
        }
    }
}
Онлайн: 0
Реклама