diff --git a/README.md b/README.md
index c8ed70c..022442f 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@ Add the extension to your `phpunit.xml.dist` or `phpunit.xml` file:
+
@@ -46,6 +47,7 @@ Add the extension to your `phpunit.xml.dist` or `phpunit.xml` file:
- **`topN`** (default: `10`): Number of slowest tests to display in the summary report
- **`showIndividualTimings`** (default: `false`): Whether to display timing for each test as it runs
+- **`showFQCN`** (default: `true`): Whether to display fully qualified class names (FQCN) or just the class name. When set to `false`, only the class name without namespace will be shown (e.g., `MyTestClass::testMethod` instead of `Phauthentic\PHPUnit\ExecutionTiming\Tests\MyTestClass::testMethod`)
- **`warningThreshold`** (default: `1.0`): Time in seconds at which tests will be colored yellow (warning). Tests with execution time >= this value will be highlighted.
- **`dangerThreshold`** (default: `5.0`): Time in seconds at which tests will be colored red (danger). Tests with execution time >= this value will be highlighted in red. Tests between `warningThreshold` and `dangerThreshold` will be colored yellow.
@@ -122,6 +124,22 @@ This configuration will:
- Show yellow for tests taking 0.5 seconds or more
- Show red for tests taking 2.0 seconds or more
+### With Short Class Names (showFQCN disabled)
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+This configuration will display only the class name without the full namespace path, making the output more compact:
+- `MyTestClass::testMethod` instead of `Phauthentic\PHPUnit\ExecutionTiming\Tests\MyTestClass::testMethod`
+
## How It Works
The extension subscribes to PHPUnit events:
diff --git a/src/ExecutionTimingExtension/ExecutionTimeExtension.php b/src/ExecutionTimingExtension/ExecutionTimeExtension.php
index 2b98ad8..ece3395 100644
--- a/src/ExecutionTimingExtension/ExecutionTimeExtension.php
+++ b/src/ExecutionTimingExtension/ExecutionTimeExtension.php
@@ -30,6 +30,7 @@ final class ExecutionTimeExtension implements Extension
private float $testStartTime = 0.0;
private int $topN = 10;
private bool $showIndividualTimings = false;
+ private bool $showFQCN = true;
private float $warningThreshold = 1.0;
private float $dangerThreshold = 5.0;
@@ -51,14 +52,15 @@ public function onTestFinished(Finished $event): void
{
$duration = microtime(true) - $this->testStartTime;
$testName = $event->test()->id();
+ $displayName = $this->formatTestName($testName);
$this->testTimes[] = [
- 'name' => $testName,
+ 'name' => $displayName,
'time' => $duration,
];
if ($this->showIndividualTimings) {
$timeMs = round($duration * 1000, 2);
- printf(" ⏱ %s: %.2f ms\n", $testName, $timeMs);
+ printf(" ⏱ %s: %.2f ms\n", $displayName, $timeMs);
}
}
@@ -109,5 +111,34 @@ public function extractConfigurationFromParameters(ParameterCollection $paramete
if ($parameters->has('dangerThreshold')) {
$this->dangerThreshold = (float)$parameters->get('dangerThreshold');
}
+
+ if ($parameters->has('showFQCN')) {
+ $this->showFQCN = filter_var(
+ $parameters->get('showFQCN'),
+ FILTER_VALIDATE_BOOLEAN
+ );
+ }
+ }
+
+ private function formatTestName(string $testName): string
+ {
+ if ($this->showFQCN) {
+ return $testName;
+ }
+
+ // Extract class name from format: Fully\Qualified\ClassName::methodName
+ if (str_contains($testName, '::')) {
+ $parts = explode('::', $testName, 2);
+ $className = $parts[0];
+ $methodName = $parts[1] ?? '';
+
+ // Get just the class name (last part of namespace)
+ $classNameParts = explode('\\', $className);
+ $shortClassName = end($classNameParts);
+
+ return $shortClassName . ($methodName !== '' ? '::' . $methodName : '');
+ }
+
+ return $testName;
}
}
diff --git a/tests/Unit/ExecutionTimeExtensionTest.php b/tests/Unit/ExecutionTimeExtensionTest.php
index d8405c8..8ba7bd0 100644
--- a/tests/Unit/ExecutionTimeExtensionTest.php
+++ b/tests/Unit/ExecutionTimeExtensionTest.php
@@ -133,4 +133,139 @@ public function testOnExecutionFinishedWithNoTests(): void
$this->assertEmpty($output);
}
+
+ public function testDefaultShowFQCNIsTrue(): void
+ {
+ $reflection = new \ReflectionClass($this->extension);
+ $property = $reflection->getProperty('showFQCN');
+ $property->setAccessible(true);
+
+ $this->assertTrue($property->getValue($this->extension));
+ }
+
+ public function testExtractConfigurationFromParametersWithShowFQCNTrue(): void
+ {
+ $parameters = ParameterCollection::fromArray([
+ 'showFQCN' => 'true',
+ ]);
+
+ $reflection = new \ReflectionClass($this->extension);
+ $method = $reflection->getMethod('extractConfigurationFromParameters');
+ $method->setAccessible(true);
+ $method->invoke($this->extension, $parameters);
+
+ $property = $reflection->getProperty('showFQCN');
+ $property->setAccessible(true);
+
+ $this->assertTrue($property->getValue($this->extension));
+ }
+
+ public function testExtractConfigurationFromParametersWithShowFQCNFalse(): void
+ {
+ $parameters = ParameterCollection::fromArray([
+ 'showFQCN' => 'false',
+ ]);
+
+ $reflection = new \ReflectionClass($this->extension);
+ $method = $reflection->getMethod('extractConfigurationFromParameters');
+ $method->setAccessible(true);
+ $method->invoke($this->extension, $parameters);
+
+ $property = $reflection->getProperty('showFQCN');
+ $property->setAccessible(true);
+
+ $this->assertFalse($property->getValue($this->extension));
+ }
+
+ public function testFormatTestNameWithFQCNEnabled(): void
+ {
+ $reflection = new \ReflectionClass($this->extension);
+ $method = $reflection->getMethod('formatTestName');
+ $method->setAccessible(true);
+
+ $testName = 'Phauthentic\\PHPUnit\\ExecutionTiming\\Tests\\Unit\\MyTestClass::testMethod';
+ $result = $method->invoke($this->extension, $testName);
+
+ $this->assertEquals('Phauthentic\\PHPUnit\\ExecutionTiming\\Tests\\Unit\\MyTestClass::testMethod', $result);
+ }
+
+ public function testFormatTestNameWithFQCNDisabled(): void
+ {
+ $parameters = ParameterCollection::fromArray([
+ 'showFQCN' => 'false',
+ ]);
+
+ $reflection = new \ReflectionClass($this->extension);
+ $extractMethod = $reflection->getMethod('extractConfigurationFromParameters');
+ $extractMethod->setAccessible(true);
+ $extractMethod->invoke($this->extension, $parameters);
+
+ $formatMethod = $reflection->getMethod('formatTestName');
+ $formatMethod->setAccessible(true);
+
+ $testName = 'Phauthentic\\PHPUnit\\ExecutionTiming\\Tests\\Unit\\MyTestClass::testMethod';
+ $result = $formatMethod->invoke($this->extension, $testName);
+
+ $this->assertEquals('MyTestClass::testMethod', $result);
+ }
+
+ public function testFormatTestNameWithFQCNDisabledAndNoNamespace(): void
+ {
+ $parameters = ParameterCollection::fromArray([
+ 'showFQCN' => 'false',
+ ]);
+
+ $reflection = new \ReflectionClass($this->extension);
+ $extractMethod = $reflection->getMethod('extractConfigurationFromParameters');
+ $extractMethod->setAccessible(true);
+ $extractMethod->invoke($this->extension, $parameters);
+
+ $formatMethod = $reflection->getMethod('formatTestName');
+ $formatMethod->setAccessible(true);
+
+ $testName = 'MyTestClass::testMethod';
+ $result = $formatMethod->invoke($this->extension, $testName);
+
+ $this->assertEquals('MyTestClass::testMethod', $result);
+ }
+
+ public function testFormatTestNameWithFQCNDisabledAndNoMethodName(): void
+ {
+ $parameters = ParameterCollection::fromArray([
+ 'showFQCN' => 'false',
+ ]);
+
+ $reflection = new \ReflectionClass($this->extension);
+ $extractMethod = $reflection->getMethod('extractConfigurationFromParameters');
+ $extractMethod->setAccessible(true);
+ $extractMethod->invoke($this->extension, $parameters);
+
+ $formatMethod = $reflection->getMethod('formatTestName');
+ $formatMethod->setAccessible(true);
+
+ $testName = 'Phauthentic\\PHPUnit\\ExecutionTiming\\Tests\\Unit\\MyTestClass';
+ $result = $formatMethod->invoke($this->extension, $testName);
+
+ $this->assertEquals('Phauthentic\\PHPUnit\\ExecutionTiming\\Tests\\Unit\\MyTestClass', $result);
+ }
+
+ public function testFormatTestNameWithFQCNDisabledAndSingleNamespaceLevel(): void
+ {
+ $parameters = ParameterCollection::fromArray([
+ 'showFQCN' => 'false',
+ ]);
+
+ $reflection = new \ReflectionClass($this->extension);
+ $extractMethod = $reflection->getMethod('extractConfigurationFromParameters');
+ $extractMethod->setAccessible(true);
+ $extractMethod->invoke($this->extension, $parameters);
+
+ $formatMethod = $reflection->getMethod('formatTestName');
+ $formatMethod->setAccessible(true);
+
+ $testName = 'MyNamespace\\MyTestClass::testMethod';
+ $result = $formatMethod->invoke($this->extension, $testName);
+
+ $this->assertEquals('MyTestClass::testMethod', $result);
+ }
}