Here is a test case class with four test methods that each uses a different string argument for the #[RequiresPhp(string $versionRequirement)] attribute:
Test.php
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
use PHPUnit\Framework\Attributes\RequiresPhp;
use PHPUnit\Framework\TestCase;
#[DoesNotPerformAssertions]
final class Test extends TestCase
{
#[RequiresPhp('8.3')]
public function testOne(): void
{
}
#[RequiresPhp('>= 8.3')]
public function testTwo(): void
{
}
#[RequiresPhp('^8.3')]
public function testThree(): void
{
}
#[RequiresPhp('~8.3')]
public function testFour(): void
{
}
}
Running the tests shown above using PHPUnit 12.3.8, PHPUnit 11.5.36, and PHPUnit 10.5.52 with PHP 8.4.12 shows the same behaviour:
❯ ./phpunit --debug Test.php
PHPUnit Started (PHPUnit 12.3.8 using PHP 8.4.12 (cli) on Linux)
Test Runner Configured
Bootstrap Finished (/usr/local/src/phpunit/tests/bootstrap.php)
Event Facade Sealed
Test Suite Loaded (4 tests)
Test Runner Started
Test Suite Sorted
Test Runner Execution Started (4 tests)
Test Suite Started (Test, 4 tests)
Test Preparation Started (Test::testOne)
Test Skipped (Test::testOne)
PHP 8.3 is required.
Test Preparation Started (Test::testTwo)
Test Prepared (Test::testTwo)
Test Passed (Test::testTwo)
Test Finished (Test::testTwo)
Test Preparation Started (Test::testThree)
Test Prepared (Test::testThree)
Test Passed (Test::testThree)
Test Finished (Test::testThree)
Test Preparation Started (Test::testFour)
Test Prepared (Test::testFour)
Test Passed (Test::testFour)
Test Finished (Test::testFour)
Test Suite Finished (Test, 4 tests)
Test Runner Execution Finished
Test Runner Finished
PHPUnit Finished (Shell Exit Code: 0)
As can be seen above, the test that is attributed with #[RequiresPhp('8.3')] is skipped on PHP 8.4.12 as the version constraint '8.3' does not match PHP 8.4.12 whereas >= 8.3, ^8.3, and ~8.3 do.
This is the current behaviour and has been since PHPUnit 10. Any change to how #[RequiresPhp('8.3')] is interpreted would be a break in backward compatibility.
Instead of changing how #[RequiresPhp('8.3')] is interpreted (as #[RequiresPhp('>= 8.3')], for example), I would rather deprecate $versionRequirement string arguments for attributes such as #[RequiresPhp(string $versionRequirement)] that do not begin with an explicit version comparison operator such as >=, ^, or ~.
Using just '8.3' has always been confusing and probably should have never been supported in the first place.
Originally posted by @sebastianbergmann in symfony/symfony#61682 (comment)
Here is a test case class with four test methods that each uses a different string argument for the
#[RequiresPhp(string $versionRequirement)]attribute:Test.phpRunning the tests shown above using PHPUnit 12.3.8, PHPUnit 11.5.36, and PHPUnit 10.5.52 with PHP 8.4.12 shows the same behaviour:
As can be seen above, the test that is attributed with
#[RequiresPhp('8.3')]is skipped on PHP 8.4.12 as the version constraint'8.3'does not match PHP 8.4.12 whereas>= 8.3,^8.3, and~8.3do.This is the current behaviour and has been since PHPUnit 10. Any change to how
#[RequiresPhp('8.3')]is interpreted would be a break in backward compatibility.Instead of changing how
#[RequiresPhp('8.3')]is interpreted (as#[RequiresPhp('>= 8.3')], for example), I would rather deprecate$versionRequirementstring arguments for attributes such as#[RequiresPhp(string $versionRequirement)]that do not begin with an explicit version comparison operator such as>=,^, or~.Using just
'8.3'has always been confusing and probably should have never been supported in the first place.Originally posted by @sebastianbergmann in symfony/symfony#61682 (comment)