/vendor/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php
PHP | 312 lines | 227 code | 49 blank | 36 comment | 38 complexity | eb5d80fd2edc743b6ee4ebf849e49c21 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 function array_key_exists;
- use function array_keys;
- use function array_map;
- use function array_pop;
- use function array_values;
- use function explode;
- use function get_class;
- use function gettype;
- use function implode;
- use function in_array;
- use function is_bool;
- use function is_float;
- use function is_int;
- use function is_numeric;
- use function is_object;
- use function is_scalar;
- use function is_string;
- use function ord;
- use function preg_quote;
- use function preg_replace;
- use function range;
- use function sprintf;
- use function str_replace;
- use function strlen;
- use function strpos;
- use function strtolower;
- use function strtoupper;
- use function substr;
- use function trim;
- use PHPUnit\Framework\TestCase;
- use PHPUnit\Util\Color;
- use PHPUnit\Util\Exception as UtilException;
- use PHPUnit\Util\Test;
- use ReflectionException;
- use ReflectionMethod;
- use ReflectionObject;
- use SebastianBergmann\Exporter\Exporter;
- /**
- * @internal This class is not covered by the backward compatibility promise for PHPUnit
- */
- final class NamePrettifier
- {
- /**
- * @var string[]
- */
- private $strings = [];
- /**
- * @var bool
- */
- private $useColor;
- public function __construct(bool $useColor = false)
- {
- $this->useColor = $useColor;
- }
- /**
- * Prettifies the name of a test class.
- *
- * @psalm-param class-string $className
- */
- public function prettifyTestClass(string $className): string
- {
- try {
- $annotations = Test::parseTestMethodAnnotations($className);
- if (isset($annotations['class']['testdox'][0])) {
- return $annotations['class']['testdox'][0];
- }
- } catch (UtilException $e) {
- // ignore, determine className by parsing the provided name
- }
- $parts = explode('\\', $className);
- $className = array_pop($parts);
- if (substr($className, -1 * strlen('Test')) === 'Test') {
- $className = substr($className, 0, strlen($className) - strlen('Test'));
- }
- if (strpos($className, 'Tests') === 0) {
- $className = substr($className, strlen('Tests'));
- } elseif (strpos($className, 'Test') === 0) {
- $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;
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- public function prettifyTestCase(TestCase $test): string
- {
- $annotations = Test::parseTestMethodAnnotations(
- get_class($test),
- $test->getName(false)
- );
- $annotationWithPlaceholders = false;
- $callback = static function (string $variable): string
- {
- return sprintf('/%s(?=\b)/', preg_quote($variable, '/'));
- };
- if (isset($annotations['method']['testdox'][0])) {
- $result = $annotations['method']['testdox'][0];
- if (strpos($result, '$') !== false) {
- $annotation = $annotations['method']['testdox'][0];
- $providedData = $this->mapTestMethodParameterNamesToProvidedDataValues($test);
- $variables = array_map($callback, array_keys($providedData));
- $result = trim(preg_replace($variables, $providedData, $annotation));
- $annotationWithPlaceholders = true;
- }
- } else {
- $result = $this->prettifyTestMethod($test->getName(false));
- }
- if (!$annotationWithPlaceholders && $test->usesDataProvider()) {
- $result .= $this->prettifyDataSet($test);
- }
- return $result;
- }
- public function prettifyDataSet(TestCase $test): string
- {
- if (!$this->useColor) {
- return $test->getDataSetAsString(false);
- }
- if (is_int($test->dataName())) {
- $data = Color::dim(' with data set ') . Color::colorize('fg-cyan', (string) $test->dataName());
- } else {
- $data = Color::dim(' with ') . Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $test->dataName()));
- }
- return $data;
- }
- /**
- * Prettifies the name of a test method.
- */
- public function prettifyTestMethod(string $name): string
- {
- $buffer = '';
- if ($name === '') {
- return $buffer;
- }
- $string = (string) preg_replace('#\d+$#', '', $name, -1, $count);
- if (in_array($string, $this->strings, true)) {
- $name = $string;
- } elseif ($count === 0) {
- $this->strings[] = $string;
- }
- if (strpos($name, 'test_') === 0) {
- $name = substr($name, 5);
- } elseif (strpos($name, 'test') === 0) {
- $name = substr($name, 4);
- }
- if ($name === '') {
- return $buffer;
- }
- $name[0] = strtoupper($name[0]);
- if (strpos($name, '_') !== false) {
- return trim(str_replace('_', ' ', $name));
- }
- $wasNumeric = false;
- foreach (range(0, strlen($name) - 1) as $i) {
- if ($i > 0 && ord($name[$i]) >= 65 && ord($name[$i]) <= 90) {
- $buffer .= ' ' . strtolower($name[$i]);
- } else {
- $isNumeric = is_numeric($name[$i]);
- if (!$wasNumeric && $isNumeric) {
- $buffer .= ' ';
- $wasNumeric = true;
- }
- if ($wasNumeric && !$isNumeric) {
- $wasNumeric = false;
- }
- $buffer .= $name[$i];
- }
- }
- return $buffer;
- }
- /**
- * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
- */
- private function mapTestMethodParameterNamesToProvidedDataValues(TestCase $test): array
- {
- try {
- $reflector = new ReflectionMethod(get_class($test), $test->getName(false));
- // @codeCoverageIgnoreStart
- } catch (ReflectionException $e) {
- throw new UtilException(
- $e->getMessage(),
- (int) $e->getCode(),
- $e
- );
- }
- // @codeCoverageIgnoreEnd
- $providedData = [];
- $providedDataValues = array_values($test->getProvidedData());
- $i = 0;
- $providedData['$_dataName'] = $test->dataName();
- foreach ($reflector->getParameters() as $parameter) {
- if (!array_key_exists($i, $providedDataValues) && $parameter->isDefaultValueAvailable()) {
- try {
- $providedDataValues[$i] = $parameter->getDefaultValue();
- // @codeCoverageIgnoreStart
- } catch (ReflectionException $e) {
- throw new UtilException(
- $e->getMessage(),
- (int) $e->getCode(),
- $e
- );
- }
- // @codeCoverageIgnoreEnd
- }
- $value = $providedDataValues[$i++] ?? null;
- if (is_object($value)) {
- $reflector = new ReflectionObject($value);
- if ($reflector->hasMethod('__toString')) {
- $value = (string) $value;
- } else {
- $value = get_class($value);
- }
- }
- if (!is_scalar($value)) {
- $value = gettype($value);
- }
- if (is_bool($value) || is_int($value) || is_float($value)) {
- $value = (new Exporter)->export($value);
- }
- if (is_string($value) && $value === '') {
- if ($this->useColor) {
- $value = Color::colorize('dim,underlined', 'empty');
- } else {
- $value = "''";
- }
- }
- $providedData['$' . $parameter->getName()] = $value;
- }
- if ($this->useColor) {
- $providedData = array_map(static function ($value)
- {
- return Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $value, true));
- }, $providedData);
- }
- return $providedData;
- }
- }