zhamao-framework/tests/ZMResultPrinter.php

203 lines
6.5 KiB
PHP
Raw Normal View History

2022-08-28 13:03:58 +08:00
<?php
declare(strict_types=1);
namespace Tests;
use PHPUnit\Framework\TestResult;
use PHPUnit\Runner\BaseTestRunner;
use PHPUnit\Runner\PhptTestCase;
use PHPUnit\Util\Color;
use PHPUnit\Util\TestDox\CliTestDoxPrinter;
class ZMResultPrinter extends CliTestDoxPrinter
{
/**
* 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' => '┴',
];
2022-11-03 10:36:08 +08:00
/* @phpstan-ignore-next-line */
2022-08-28 13:03:58 +08:00
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' => 'fg-red',
],
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',
],
];
public function printResult(TestResult $result): void
{
$this->writeNewLine();
$this->write($this->colorizeTextBox('fg-white,bold', 'Tests: '));
$counts = [
BaseTestRunner::STATUS_FAILURE => ['failed', $result->failureCount()],
BaseTestRunner::STATUS_ERROR => ['errors', $result->errorCount()],
BaseTestRunner::STATUS_SKIPPED => ['skipped', $result->skippedCount()],
BaseTestRunner::STATUS_RISKY => ['risky', $result->riskyCount()],
BaseTestRunner::STATUS_INCOMPLETE => ['incomplete', $result->notImplementedCount()],
BaseTestRunner::STATUS_WARNING => ['warnings', $result->warningCount()],
BaseTestRunner::STATUS_PASSED => ['passed', count($result->passed())],
];
$counters = [];
foreach ($counts as $status => $count) {
if ($count[1] > 0) {
$counters[] = $this->colorizeTextBox(self::STATUS_STYLES[$status]['color'], "{$count[1]} {$count[0]}");
}
}
$this->writeWithColor('fg-white,bold', implode(', ', $counters));
$this->write($this->colorizeTextBox('fg-white,bold', 'Time: '));
$this->writeWithColor('fg-default', sprintf('%fs', $result->time()));
$this->printFooter($result);
}
protected function printFooter(TestResult $result): void
{
if ($result->failureCount() === 0) {
$color = 'bg-green,fg-white,bold';
$text = '[OK] No errors';
} else {
$color = 'bg-red,fg-white,bold';
$text = '[ERROR] Found ' . $result->failureCount() . ' failures';
}
$this->writeWithColor($color, "\n {$text} ");
}
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']) {
[$class_short, $class_long] = explode(' (', $result['className']);
$this->write($this->colorizeTextBox('fg-black,bg-cyan', " {$class_short} "));
$this->write(' ' . rtrim($class_long, ')') . PHP_EOL);
}
// test result line
if ($this->colors && $result['className'] === PhptTestCase::class) {
$testName = Color::colorizePath($result['testName'], $prevResult['testName'], true);
} else {
$testName = $result['testMethod'];
}
$testName = strtolower($testName);
$style = self::STATUS_STYLES[$result['status']];
$line = sprintf(
' %s %s',
$this->colorizeTextBox($style['color'], $style['symbol']),
$this->colorizeTextBox('dim', $testName),
);
$this->write($line);
// additional information when verbose
$this->writeNewLine();
if (!empty($result['message'])) {
$this->write(' ' . $result['message']);
}
}
protected function formatTestResultMessage(\Throwable $t, array $result, ?string $prefix = null): string
2022-08-28 13:03:58 +08:00
{
$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 fn ($p) => Color::colorize($color, $p), self::PREFIX_DECORATED);
2022-08-28 13:03:58 +08:00
}
$out = '';
if ($message) {
2022-12-25 19:29:44 +08:00
$out .= $this->prefixLines($prefix['message'], $message . PHP_EOL) . PHP_EOL;
2022-08-28 13:03:58 +08:00
}
if ($diff) {
$out .= $this->prefixLines($prefix['diff'], $diff . PHP_EOL) . PHP_EOL;
}
return $out;
}
}