From ada3fe482da8096f8a1b230e8439076f1f17c862 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Tue, 20 Oct 2026 10:50:46 +0200 Subject: [PATCH 1/2] Support PHPUnit 10+ and count assertions Skip scenarios with Assert::markTestSkipped() instead of throwing PHPUnit\Framework\SkippedTestError, which was removed in PHPUnit 10. Make the see* steps use PHPUnit assertions so that Codeception counts them; previously only failures were recorded, so passing runs reported "Assertions: 0". Allow PHPUnit 10-12 and Psalm 7 in dev dependencies, run CI on ubuntu-latest with PHP up to 8.4, and adjust the fixtures for Psalm 7's purity checks. Claude-Session: https://claude.ai/code/session_01WNSb29tptiTQoc44Tk7XZW --- .github/workflows/ci.yml | 8 +++---- composer.json | 4 ++-- src/Module.php | 35 ++++++++++------------------ tests/acceptance/PsalmModule.feature | 6 ++--- 4 files changed, 21 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6870c44..271f217 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: jobs: psalm: name: Static analysis - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 @@ -60,7 +60,7 @@ jobs: phpcs: name: Code style - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 @@ -100,11 +100,11 @@ jobs: tests: name: Test on ${{matrix.php}} - ${{matrix.deps}} deps - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest continue-on-error: ${{matrix.php == '8.0'}} strategy: matrix: - php: ['7.4', '8.0', '8.1'] + php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] deps: ['high', 'low', 'stable'] fail-fast: false steps: diff --git a/composer.json b/composer.json index 75cb82e..37de484 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,8 @@ }, "require-dev": { "squizlabs/php_codesniffer": "^3.4", - "vimeo/psalm": "^4.17.0 || dev-master || ^5.0.0 || ^6.0.0 || dev-master", - "phpunit/phpunit": "^9.5.20", + "vimeo/psalm": "^4.17.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-rc1 || dev-master", + "phpunit/phpunit": "^9.5.20 || ^10.5 || ^11.5 || ^12.0", "codeception/codeception": "^4.1.31 || ^5.0.0-rc3" }, "scripts": { diff --git a/src/Module.php b/src/Module.php index c265f61..199b9d3 100644 --- a/src/Module.php +++ b/src/Module.php @@ -20,7 +20,6 @@ use PHPUnit\Framework\Assert; use Behat\Gherkin\Node\TableNode; use OutOfBoundsException; -use PHPUnit\Framework\SkippedTestError; use RuntimeException; use function is_array; @@ -172,31 +171,27 @@ public function seeExitCode($exitCode): void $exitCode = (int) $exitCode; - if ($this->exitCode === $exitCode) { - return; - } - - Assert::fail("Expected exit code {$exitCode}, got {$this->exitCode}"); + Assert::assertSame($exitCode, $this->exitCode, "Expected exit code {$exitCode}, got {$this->exitCode}"); } public function seeThisError(string $type, string $message): void { $this->parseErrors(); - if (empty($this->errors)) { - Assert::fail("No errors"); - } + Assert::assertNotEmpty($this->errors, "No errors"); + $matching = null; foreach ($this->errors as $i => $error) { if ( $this->matches($type, $error['type']) && $this->matches($message, $error['message']) ) { - unset($this->errors[$i]); - return; + $matching = $i; + break; } } - Assert::fail("Didn't see [ $type $message ] in: \n" . $this->remainingErrors()); + Assert::assertNotNull($matching, "Didn't see [ $type $message ] in: \n" . $this->remainingErrors()); + unset($this->errors[$matching]); } private function matches(string $expected, string $actual): bool @@ -222,9 +217,7 @@ private function matches(string $expected, string $actual): bool public function seeNoErrors(): void { $this->parseErrors(); - if (!empty($this->errors)) { - Assert::fail("There were errors: \n" . $this->remainingErrors()); - } + Assert::assertEmpty($this->errors, "There were errors: \n" . $this->remainingErrors()); } private function packageSatisfiesVersionConstraint(string $package, string $versionConstraint): bool @@ -304,8 +297,7 @@ public function seePsalmHasTaintAnalysis(): bool public function havePsalmWithTaintAnalysis(): void { if (!$this->seePsalmHasTaintAnalysis()) { - /** @psalm-suppress InternalClass,InternalMethod */ - throw new SkippedTestError("This scenario requires Psalm with taint analysis (3.10+)"); + Assert::markTestSkipped("This scenario requires Psalm with taint analysis (3.10+)"); } } @@ -376,8 +368,7 @@ public function haveTheFollowingCode($code): void */ public function haveSomeFuturePsalmThatSupportsThisFeature(string $ref): void { - /** @psalm-suppress InternalClass,InternalMethod */ - throw new SkippedTestError("Future functionality that Psalm has yet to support: $ref"); + Assert::markTestSkipped("Future functionality that Psalm has yet to support: $ref"); } /** @@ -396,8 +387,7 @@ public function havePsalmOfACertainVersionRangeBecauseOf(string $operator, strin $op = (string) self::VERSION_OPERATORS[$operator]; if (!$this->packageSatisfiesVersionConstraint('vimeo/psalm', $op . $version)) { - /** @psalm-suppress InternalClass,InternalMethod */ - throw new SkippedTestError("This scenario requires Psalm $op $version because of $reason"); + Assert::markTestSkipped("This scenario requires Psalm $op $version because of $reason"); } } @@ -482,8 +472,7 @@ public function haveADependencySatisfied(string $package, string $versionConstra return; } - /** @psalm-suppress InternalClass,InternalMethod */ - throw new SkippedTestError("This scenario requires $package to match $versionConstraint"); + Assert::markTestSkipped("This scenario requires $package to match $versionConstraint"); } /** @return non-empty-string */ diff --git a/tests/acceptance/PsalmModule.feature b/tests/acceptance/PsalmModule.feature index f1371cf..550f2c4 100644 --- a/tests/acceptance/PsalmModule.feature +++ b/tests/acceptance/PsalmModule.feature @@ -7,7 +7,7 @@ Feature: Psalm module Given I have the following code preamble """ Date: Tue, 20 Oct 2026 11:18:04 +0200 Subject: [PATCH 2/2] Skip lowest dependencies on PHP 8.4 in CI The lowest allowed Psalm versions crash on PHP 8.4. Claude-Session: https://claude.ai/code/session_01WNSb29tptiTQoc44Tk7XZW --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 271f217..ab4f05e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,6 +106,10 @@ jobs: matrix: php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] deps: ['high', 'low', 'stable'] + exclude: + # the lowest Psalm versions crash on PHP 8.4 + - php: '8.4' + deps: 'low' fail-fast: false steps: - name: Checkout