diff --git a/composer.json b/composer.json index e81f8c7..cc6f32d 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ }, "require": { "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "allure-framework/allure-php-commons": "^2.4", + "allure-framework/allure-php-commons": "^2.5.0", "phpunit/phpunit": "^10.0.5 || ^11 || ^12.0.1 || ^13" }, "require-dev": { diff --git a/test/report/Generate/DataProviderTest.php b/test/report/Generate/DataProviderTest.php index 90a8cf8..d450167 100644 --- a/test/report/Generate/DataProviderTest.php +++ b/test/report/Generate/DataProviderTest.php @@ -24,7 +24,6 @@ public static function providerNamed(): iterable { return [ 'Simple name' => [1, 1], - '' => [2, 2], '"Double-quoted" name' => [3, 3], "'Single-quoted' name" => [4, 4], ' ' => [5, 5], diff --git a/test/unit/AllureAdapterTest.php b/test/unit/AllureAdapterTest.php index eb19376..c91a4ef 100644 --- a/test/unit/AllureAdapterTest.php +++ b/test/unit/AllureAdapterTest.php @@ -84,7 +84,7 @@ class: null, thread: null, ); $this->expectException(LogicException::class); - $this->expectExceptionMessage('Container not registered: a'); + $this->expectExceptionMessageMatches('~Container not registered: a~'); $adapter->getContainerId($info); } @@ -115,7 +115,7 @@ class: null, thread: null, ); $this->expectException(LogicException::class); - $this->expectExceptionMessage('Test not registered: a'); + $this->expectExceptionMessageMatches('~Test not registered: a~'); $adapter->getTestId($info); } diff --git a/test/unit/Event/EventTestTrait.php b/test/unit/Event/EventTestTrait.php index 5557fd0..4da9dd4 100644 --- a/test/unit/Event/EventTestTrait.php +++ b/test/unit/Event/EventTestTrait.php @@ -9,6 +9,7 @@ use PHPUnit\Event\Code\TestDox; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\Telemetry\CpuTime; use PHPUnit\Event\Telemetry\Duration; use PHPUnit\Event\Telemetry\GarbageCollectorStatus; use PHPUnit\Event\Telemetry\HRTime; @@ -40,8 +41,21 @@ protected function createTelemetryInfo(): Info { $garbageCollectorStatus = self::createGarbageCollectorStatus(); + // PHPUnit 13 added CPU times to the snapshot and telemetry info. + $cpuTimes = []; + $cpuTimeDeltas = []; + if (class_exists(CpuTime::class)) { + /** @psalm-suppress MixedAssignment CpuTime is unavailable on older PHPUnit versions. */ + $zeroCpuTime = CpuTime::fromSecondsAndNanoseconds(0, 0); + $cpuTimes = [$zeroCpuTime, $zeroCpuTime, $zeroCpuTime]; + $cpuTimeDeltas = [...$cpuTimes, ...$cpuTimes]; + } + /** + * @psalm-suppress TooFewArguments * @psalm-suppress TooManyArguments + * @psalm-suppress InvalidArgument PHPUnit 13 requires the CPU time arguments. + * @psalm-suppress InternalMethod * @psalm-suppress PossiblyNullArgument */ $snapshot = new Snapshot( @@ -49,14 +63,22 @@ protected function createTelemetryInfo(): Info MemoryUsage::fromBytes(0), MemoryUsage::fromBytes(0), $garbageCollectorStatus, + ...$cpuTimes, ); + /** + * @psalm-suppress TooFewArguments + * @psalm-suppress TooManyArguments + * @psalm-suppress InvalidArgument PHPUnit 13 requires the CPU time arguments. + * @psalm-suppress InternalMethod + */ return new Info( $snapshot, Duration::fromSecondsAndNanoseconds(0, 0), MemoryUsage::fromBytes(0), Duration::fromSecondsAndNanoseconds(0, 0), MemoryUsage::fromBytes(0), + ...$cpuTimeDeltas, ); } @@ -76,6 +98,7 @@ protected function createTestMethod( * @var non-empty-string $methodName * @var TestDox $testDox * @psalm-suppress InaccessibleMethod + * @psalm-suppress InternalMethod */ $testDox = method_exists(TestDox::class, 'fromClassNameAndMethodName') ? TestDox::fromClassNameAndMethodName($class, $methodName) // early PHPUnit 10 @@ -111,6 +134,7 @@ protected function createThrowable( /** * @var Throwable * @psalm-suppress InaccessibleMethod + * @psalm-suppress InternalMethod */ return method_exists(Throwable::class, 'from') ? Throwable::from($throwable) // early PHPUnit 10 @@ -129,7 +153,10 @@ protected function createTestConsideredRiskyEvent( ): ConsideredRisky { $message ??= 'message'; - /** @var non-empty-string $message */ + /** + * @var non-empty-string $message + * @psalm-suppress InternalMethod + */ return new ConsideredRisky( $this->createTelemetryInfo(), $test, @@ -141,6 +168,7 @@ protected function createTestErroredEvent( Test $test, ?string $message = null, ): Errored { + /** @psalm-suppress InternalMethod */ return new Errored( $this->createTelemetryInfo(), $test, @@ -154,6 +182,7 @@ protected function createTestFailedEvent( Test $test, ?string $message = null, ): Failed { + /** @psalm-suppress InternalMethod */ return new Failed( $this->createTelemetryInfo(), $test, @@ -167,6 +196,7 @@ protected function createTestFailedEvent( protected function createTestFinishedEvent( Test $test, ): Finished { + /** @psalm-suppress InternalMethod */ return new Finished( $this->createTelemetryInfo(), $test, @@ -178,6 +208,7 @@ protected function createTestMarkedIncompleteEvent( Test $test, ?string $message = null, ): MarkedIncomplete { + /** @psalm-suppress InternalMethod */ return new MarkedIncomplete( $this->createTelemetryInfo(), $test, @@ -190,6 +221,7 @@ protected function createTestMarkedIncompleteEvent( protected function createTestPassesEvent( Test $test, ): Passed { + /** @psalm-suppress InternalMethod */ return new Passed( $this->createTelemetryInfo(), $test, @@ -199,6 +231,7 @@ protected function createTestPassesEvent( protected function createTestPreparationStartedEvent( Test $test, ): PreparationStarted { + /** @psalm-suppress InternalMethod */ return new PreparationStarted( $this->createTelemetryInfo(), $test, @@ -208,6 +241,7 @@ protected function createTestPreparationStartedEvent( protected function createTestPreparedEvent( Test $test, ): Prepared { + /** @psalm-suppress InternalMethod */ return new Prepared( $this->createTelemetryInfo(), $test, @@ -218,6 +252,7 @@ protected function createTestSkippedEvent( Test $test, ?string $message = null, ): Skipped { + /** @psalm-suppress InternalMethod */ return new Skipped( $this->createTelemetryInfo(), $test, @@ -234,6 +269,7 @@ protected function createTestWarningTriggeredEvent( /** * @var non-empty-string $message * @psalm-suppress TooManyArguments + * @psalm-suppress InternalMethod */ return new WarningTriggered( $this->createTelemetryInfo(), @@ -258,6 +294,7 @@ private static function createGarbageCollectorStatus(): ?GarbageCollectorStatus if (isset($ctorInfo)) { /** * @psalm-suppress InvalidArgument + * @psalm-suppress InternalMethod * @psalm-suppress TooFewArguments * @psalm-suppress TooManyArguments */ diff --git a/test/unit/Internal/ConfigTest.php b/test/unit/Internal/ConfigTest.php index a2e118d..ec66139 100644 --- a/test/unit/Internal/ConfigTest.php +++ b/test/unit/Internal/ConfigTest.php @@ -15,6 +15,8 @@ use RuntimeException; use stdClass; +use function preg_quote; + #[CoversClass(Config::class)] final class ConfigTest extends TestCase { @@ -46,7 +48,7 @@ public function testGetOutputDirectory_InvalidData_ThrowsException(): void { $config = new Config(['outputDirectory' => 1]); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Config key "outputDirectory" should contain a string'); + $this->expectExceptionMessageMatches('~Config key "outputDirectory" should contain a string~'); $config->getOutputDirectory(); } @@ -73,7 +75,7 @@ public function testGetLinkTemplates_InvalidData_ThrowsException(): void { $config = new Config(['linkTemplates' => 1]); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Config key "linkTemplates" should contain an array'); + $this->expectExceptionMessageMatches('~Config key "linkTemplates" should contain an array~'); $config->getLinkTemplates(); } @@ -84,7 +86,9 @@ public function testGetLinkTemplates_InvalidKeyInData_ThrowsException(): void ]; $config = new Config($data); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Config key "linkTemplates" should contain an array with string keys only'); + $this->expectExceptionMessageMatches( + '~Config key "linkTemplates" should contain an array with string keys only~', + ); $config->getLinkTemplates(); } @@ -107,8 +111,9 @@ public function testGetLinkTemplates_InvalidTypeInData_ThrowsException(): void ]; $config = new Config($data); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Config key "linkTemplates/tms" contains invalid source of Qameta\Allure\Setup\LinkTemplateInterface', + $this->expectExceptionMessageMatches( + '~Config key "linkTemplates/tms" contains invalid source of ' . + preg_quote(LinkTemplateInterface::class, '~') . '~', ); $config->getLinkTemplates(); } @@ -131,9 +136,9 @@ public function testGetLinkTemplates_InvalidClassNameInData_ThrowsException(): v ]; $config = new Config($data); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Config key "linkTemplates/tms" contains ' . - 'invalid source of Qameta\Allure\Setup\LinkTemplateInterface', + $this->expectExceptionMessageMatches( + '~Config key "linkTemplates/tms" contains invalid source of ' . + preg_quote(LinkTemplateInterface::class, '~') . '~', ); $config->getLinkTemplates(); } @@ -171,7 +176,7 @@ public function testGetSetupHook_InvalidTypeInData_ThrowsException(array $data): { $config = new Config($data); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Config key "setupHook" should contain a callable'); + $this->expectExceptionMessageMatches('~Config key "setupHook" should contain a callable~'); $config->getSetupHook(); } @@ -221,9 +226,9 @@ public function testGetThreadDetector_InvalidTypeInData_ThrowsException(): void { $config = new Config(['threadDetector' => 1]); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Config key "threadDetector" contains ' . - 'invalid source of Qameta\Allure\PHPUnit\Setup\ThreadDetectorInterface', + $this->expectExceptionMessageMatches( + '~Config key "threadDetector" contains invalid source of ' . + preg_quote(ThreadDetectorInterface::class, '~') . '~', ); $config->getThreadDetector(); } @@ -246,9 +251,9 @@ public function testGetThreadDetector_InvalidClassInData_ThrowsException(): void { $config = new Config(['threadDetector' => stdClass::class]); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Config key "threadDetector" contains ' . - 'invalid source of Qameta\Allure\PHPUnit\Setup\ThreadDetectorInterface', + $this->expectExceptionMessageMatches( + '~Config key "threadDetector" contains invalid source of ' . + preg_quote(ThreadDetectorInterface::class, '~') . '~', ); $config->getThreadDetector(); } @@ -287,8 +292,8 @@ public function testGetLifecycleHooks_InvalidIndexInData_ThrowsException(): void ]; $config = new Config($data); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Config key "lifecycleHooks" should contain an array with integer keys only', + $this->expectExceptionMessageMatches( + '~Config key "lifecycleHooks" should contain an array with integer keys only~', ); $config->getLifecycleHooks(); } @@ -317,9 +322,9 @@ public function testGetLifecycleHooks_InvalidTypeInData_ThrowsException(): void { $config = new Config(['lifecycleHooks' => [1]]); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Config key "lifecycleHooks/0" contains ' . - 'invalid source of Qameta\Allure\Hook\LifecycleHookInterface', + $this->expectExceptionMessageMatches( + '~Config key "lifecycleHooks/0" contains invalid source of ' . + preg_quote(LifecycleHookInterface::class, '~') . '~', ); $config->getLifecycleHooks(); }