class NamePrettifier
@no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
@internal This class is not covered by the backward compatibility promise for PHPUnit
Hierarchy
- class \PHPUnit\Logging\TestDox\NamePrettifier
Expanded class hierarchy of NamePrettifier
1 file declares its use of NamePrettifier
- TestDoxBuilder.php in vendor/
phpunit/ phpunit/ src/ Event/ Value/ Test/ TestDoxBuilder.php
File
-
vendor/
phpunit/ phpunit/ src/ Logging/ TestDox/ NamePrettifier.php, line 55
Namespace
PHPUnit\Logging\TestDoxView source
final class NamePrettifier {
/**
* @psalm-var array<string, int>
*/
private static array $strings = [];
/**
* @psalm-param class-string $className
*/
public function prettifyTestClassName(string $className) : string {
if (class_exists($className)) {
$classLevelTestDox = MetadataRegistry::parser()->forClass($className)
->isTestDox();
if ($classLevelTestDox->isNotEmpty()) {
$classLevelTestDox = $classLevelTestDox->asArray()[0];
assert($classLevelTestDox instanceof TestDox);
return $classLevelTestDox->text();
}
}
$parts = explode('\\', $className);
$className = array_pop($parts);
if (str_ends_with($className, 'Test')) {
$className = substr($className, 0, strlen($className) - strlen('Test'));
}
if (str_starts_with($className, 'Tests')) {
$className = substr($className, strlen('Tests'));
}
elseif (str_starts_with($className, 'Test')) {
$className = substr($className, strlen('Test'));
}
if (empty($className)) {
$className = 'UnnamedTests';
}
if (!empty($parts)) {
$parts[] = $className;
$fullyQualifiedName = implode('\\', $parts);
}
else {
$fullyQualifiedName = $className;
}
$result = preg_replace('/(?<=[[:lower:]])(?=[[:upper:]])/u', ' ', $className);
if ($fullyQualifiedName !== $className) {
return $result . ' (' . $fullyQualifiedName . ')';
}
return $result;
}
// NOTE: this method is on a hot path and very performance sensitive. change with care.
public function prettifyTestMethodName(string $name) : string {
if ($name === '') {
return '';
}
$string = rtrim($name, '0123456789');
if (array_key_exists($string, self::$strings)) {
$name = $string;
}
elseif ($string === $name) {
self::$strings[$string] = 1;
}
if (str_starts_with($name, 'test_')) {
$name = substr($name, 5);
}
elseif (str_starts_with($name, 'test')) {
$name = substr($name, 4);
}
if ($name === '') {
return '';
}
$name[0] = strtoupper($name[0]);
$noUnderscore = str_replace('_', ' ', $name);
if ($noUnderscore !== $name) {
return trim($noUnderscore);
}
$wasNumeric = false;
$buffer = '';
$len = strlen($name);
for ($i = 0; $i < $len; $i++) {
if ($i > 0 && $name[$i] >= 'A' && $name[$i] <= 'Z') {
$buffer .= ' ' . strtolower($name[$i]);
}
else {
$isNumeric = $name[$i] >= '0' && $name[$i] <= '9';
if (!$wasNumeric && $isNumeric) {
$buffer .= ' ';
$wasNumeric = true;
}
if ($wasNumeric && !$isNumeric) {
$wasNumeric = false;
}
$buffer .= $name[$i];
}
}
return $buffer;
}
public function prettifyTestCase(TestCase $test, bool $colorize) : string {
$annotationWithPlaceholders = false;
$methodLevelTestDox = MetadataRegistry::parser()->forMethod($test::class, $test->name())
->isTestDox()
->isMethodLevel();
if ($methodLevelTestDox->isNotEmpty()) {
$methodLevelTestDox = $methodLevelTestDox->asArray()[0];
assert($methodLevelTestDox instanceof TestDox);
$result = $methodLevelTestDox->text();
if (str_contains($result, '$')) {
$annotation = $result;
$providedData = $this->mapTestMethodParameterNamesToProvidedDataValues($test, $colorize);
$variables = array_map(static fn(string $variable): string => sprintf('/%s(?=\\b)/', preg_quote($variable, '/')), array_keys($providedData));
$result = preg_replace($variables, $providedData, $annotation);
$annotationWithPlaceholders = true;
}
}
else {
$result = $this->prettifyTestMethodName($test->name());
}
if (!$annotationWithPlaceholders && $test->usesDataProvider()) {
$result .= $this->prettifyDataSet($test, $colorize);
}
return $result;
}
public function prettifyDataSet(TestCase $test, bool $colorize) : string {
if (!$colorize) {
return $test->dataSetAsString();
}
if (is_int($test->dataName())) {
return Color::dim(' with data set ') . Color::colorize('fg-cyan', (string) $test->dataName());
}
return Color::dim(' with ') . Color::colorize('fg-cyan', Color::visualizeWhitespace($test->dataName()));
}
private function mapTestMethodParameterNamesToProvidedDataValues(TestCase $test, bool $colorize) : array {
assert(method_exists($test, $test->name()));
/** @noinspection PhpUnhandledExceptionInspection */
$reflector = new ReflectionMethod($test::class, $test->name());
$providedData = [];
$providedDataValues = array_values($test->providedData());
$i = 0;
$providedData['$_dataName'] = $test->dataName();
foreach ($reflector->getParameters() as $parameter) {
if (!array_key_exists($i, $providedDataValues) && $parameter->isDefaultValueAvailable()) {
$providedDataValues[$i] = $parameter->getDefaultValue();
}
$value = $providedDataValues[$i++] ?? null;
if (is_object($value)) {
$reflector = new ReflectionObject($value);
if ($reflector->isEnum()) {
$enumReflector = new ReflectionEnum($value);
if ($enumReflector->isBacked()) {
$value = $value->value;
}
else {
$value = $value->name;
}
}
elseif ($reflector->hasMethod('__toString')) {
$value = (string) $value;
}
else {
$value = $value::class;
}
}
if (!is_scalar($value)) {
$value = gettype($value);
if ($value === 'NULL') {
$value = 'null';
}
}
if (is_bool($value) || is_int($value) || is_float($value)) {
$value = (new Exporter())->export($value);
}
if ($value === '') {
if ($colorize) {
$value = Color::colorize('dim,underlined', 'empty');
}
else {
$value = "''";
}
}
$providedData['$' . $parameter->getName()] = str_replace('$', '\\$', $value);
}
if ($colorize) {
$providedData = array_map(static fn($value) => Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $value, true)), $providedData);
}
return $providedData;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary |
---|---|---|---|
NamePrettifier::$strings | private static | property | @psalm-var array<string, int> |
NamePrettifier::mapTestMethodParameterNamesToProvidedDataValues | private | function | |
NamePrettifier::prettifyDataSet | public | function | |
NamePrettifier::prettifyTestCase | public | function | |
NamePrettifier::prettifyTestClassName | public | function | @psalm-param class-string $className |
NamePrettifier::prettifyTestMethodName | public | function |