mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-02 14:25:38 +08:00
add custom phpunit printer (#164)
This commit is contained in:
@@ -8,6 +8,7 @@ const ZM_TEST_LOG_DEBUG = false;
|
|||||||
use OneBot\Driver\Event\Process\WorkerStartEvent;
|
use OneBot\Driver\Event\Process\WorkerStartEvent;
|
||||||
use PHPUnit\TextUI\Command;
|
use PHPUnit\TextUI\Command;
|
||||||
use Swoole\Atomic;
|
use Swoole\Atomic;
|
||||||
|
use Tests\ZMResultPrinter;
|
||||||
use ZM\Command\Server\ServerStartCommand;
|
use ZM\Command\Server\ServerStartCommand;
|
||||||
use ZM\Event\EventProvider;
|
use ZM\Event\EventProvider;
|
||||||
use ZM\Framework;
|
use ZM\Framework;
|
||||||
@@ -37,11 +38,10 @@ ob_event_provider()->addEventListener(WorkerStartEvent::getName(), function () {
|
|||||||
if (($error['type'] ?? 0) != 0) {
|
if (($error['type'] ?? 0) != 0) {
|
||||||
logger()->emergency(zm_internal_errcode('E00027') . 'Internal fatal error: ' . $error['message'] . ' at ' . $error['file'] . "({$error['line']})");
|
logger()->emergency(zm_internal_errcode('E00027') . 'Internal fatal error: ' . $error['message'] . ' at ' . $error['file'] . "({$error['line']})");
|
||||||
}
|
}
|
||||||
ob_dump($error);
|
|
||||||
ob_dump(func_get_args());
|
|
||||||
ob_dump(debug_backtrace());
|
|
||||||
Framework::getInstance()->stop();
|
Framework::getInstance()->stop();
|
||||||
});
|
});
|
||||||
|
$_SERVER['argv'][] = '--printer';
|
||||||
|
$_SERVER['argv'][] = ZMResultPrinter::class;
|
||||||
try {
|
try {
|
||||||
// 不退出,而是返回 code
|
// 不退出,而是返回 code
|
||||||
$retcode = Command::main(false);
|
$retcode = Command::main(false);
|
||||||
|
|||||||
204
tests/ZMResultPrinter.php
Normal file
204
tests/ZMResultPrinter.php
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<?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;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
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' => '┴',
|
||||||
|
];
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
$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);
|
||||||
|
}
|
||||||
|
|
||||||
|
$out = '';
|
||||||
|
|
||||||
|
if ($message) {
|
||||||
|
$out .= $this->prefixLines($prefix['message'], strtolower($message) . PHP_EOL) . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($diff) {
|
||||||
|
$out .= $this->prefixLines($prefix['diff'], $diff . PHP_EOL) . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user