From f4ccbac7ad5935d347b436934b0e8545ff2818af Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Sat, 10 Oct 2026 00:15:34 +0400 Subject: [PATCH 1/2] feat: require PHP 8.2 Testo, which the test suite moves to next, needs PHP 8.2. Psalm is constrained to ^6 || ^7 so that it installs on the whole supported PHP range. Assisted-By: Claude Opus 5.5 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e1dceef..8ff7d3a 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ } ], "require": { - "php": ">=8.1", + "php": ">=8.2", "roadrunner-php/roadrunner-api-dto": "^1.4", "spiral/roadrunner": "^2023.2 || ^2024.1 || ^2025.1", "spiral/goridge": "^4.0", @@ -50,7 +50,7 @@ "mockery/mockery": "^1.5", "phpunit/phpunit": "^10.0", "spiral/code-style": "^2.3.1", - "vimeo/psalm": ">=5.8" + "vimeo/psalm": "^6 || ^7" }, "autoload-dev": { "psr-4": { From 21117123b775ff192ea016ee45096cd1c6df499b Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Sat, 10 Oct 2026 00:18:21 +0400 Subject: [PATCH 2/2] test: migrate from PHPUnit to Testo Mocks stay on Mockery: Double needs PHP 8.3, and the Testo Mockery plugin now verifies expectations after every test, which the PHPUnit suite never did (Mockery::close() was not called). The empty TestCase base is gone since Testo discovers tests by attribute. Assisted-By: Claude Opus 5.5 --- .gitattributes | 2 +- .github/workflows/phpunit.yml | 16 ---------- .github/workflows/testo.yml | 17 +++++++++++ .gitignore | 2 -- composer.json | 5 ++-- phpunit.xml | 18 ----------- testo.php | 23 ++++++++++++++ tests/ManagerTest.php | 56 +++++++++++++++++------------------ tests/TestCase.php | 9 ------ 9 files changed, 71 insertions(+), 77 deletions(-) delete mode 100644 .github/workflows/phpunit.yml create mode 100644 .github/workflows/testo.yml delete mode 100644 phpunit.xml create mode 100644 testo.php delete mode 100644 tests/TestCase.php diff --git a/.gitattributes b/.gitattributes index 03f5353..944fa47 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,5 +4,5 @@ .gitattributes export-ignore .gitignore export-ignore .travis.yml export-ignore -phpunit.xml export-ignore +testo.php export-ignore monorepo-builder.php export-ignore diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml deleted file mode 100644 index af84cc7..0000000 --- a/.github/workflows/phpunit.yml +++ /dev/null @@ -1,16 +0,0 @@ -on: - push: - branches: - - '*.*' - pull_request: null - -name: phpunit - -jobs: - phpunit: - uses: spiral/gh-actions/.github/workflows/phpunit.yml@master - with: - os: >- - ['ubuntu-latest'] - stability: >- - ['prefer-stable'] diff --git a/.github/workflows/testo.yml b/.github/workflows/testo.yml new file mode 100644 index 0000000..ac54aa4 --- /dev/null +++ b/.github/workflows/testo.yml @@ -0,0 +1,17 @@ +on: + push: + branches: + - 2.x + pull_request: ~ + +name: testo + +permissions: + contents: read + +jobs: + testo: + uses: spiral/gh-actions/.github/workflows/testo.yml@master + with: + os: >- + ['ubuntu-latest'] diff --git a/.gitignore b/.gitignore index cb52aae..415d0c3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,6 @@ Thumbs.db *.exe # Other -.phpunit.result.cache -.phpunit.cache/ .php_cs.cache clover.xml .env diff --git a/composer.json b/composer.json index 8ff7d3a..a6e7777 100644 --- a/composer.json +++ b/composer.json @@ -48,8 +48,9 @@ }, "require-dev": { "mockery/mockery": "^1.5", - "phpunit/phpunit": "^10.0", "spiral/code-style": "^2.3.1", + "testo/bridge-mockery": "^0.1.2", + "testo/testo": "^0.10.55", "vimeo/psalm": "^6 || ^7" }, "autoload-dev": { @@ -60,7 +61,7 @@ "scripts": { "cs:diff": "php-cs-fixer fix --dry-run -v --diff", "cs:fix": "php-cs-fixer fix -v", - "tests": "phpunit", + "test": "testo", "psalm": "psalm --no-cache" }, "config": { diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index c7e67a2..0000000 --- a/phpunit.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - src - - - - tests - - - - - - diff --git a/testo.php b/testo.php new file mode 100644 index 0000000..fa45e1e --- /dev/null +++ b/testo.php @@ -0,0 +1,23 @@ +manager->list(); - $this->assertSame(['foo', 'bar', 'baz'], $result); + Assert::same($result, ['foo', 'bar', 'baz']); } public function testListServicesWithErrorsShouldThrowAnException(): void { - $this->expectException(ServiceException::class); - $this->expectExceptionMessage('Something went wrong'); + Expect::exception(ServiceException::class)->withMessageContaining('Something went wrong'); $this->rpc ->shouldReceive('call') @@ -71,25 +75,22 @@ public function testServiceShouldBeCreated(): void }) ->andReturn(new Response(['ok' => true])); - $this->assertTrue( - $this->manager->create( - 'foo', - 'bar', - 5, - 7, - true, - ['FOO' => 'bar', 'BAZ' => 'foo'], - 50, - true, - 10, - ), - ); + Assert::true($this->manager->create( + 'foo', + 'bar', + 5, + 7, + true, + ['FOO' => 'bar', 'BAZ' => 'foo'], + 50, + true, + 10, + )); } public function testServiceCreateWithErrorsShouldThrowAnException(): void { - $this->expectException(ServiceException::class); - $this->expectExceptionMessage('Something went wrong'); + Expect::exception(ServiceException::class)->withMessageContaining('Something went wrong'); $this->rpc ->shouldReceive('call') @@ -111,13 +112,12 @@ public function testServiceShouldBeRestarted(): void }) ->andReturn(new Response(['ok' => true])); - $this->assertTrue($this->manager->restart('foo')); + Assert::true($this->manager->restart('foo')); } public function testServiceRestartWithErrorsShouldThrowAnException(): void { - $this->expectException(ServiceException::class); - $this->expectExceptionMessage('Something went wrong'); + Expect::exception(ServiceException::class)->withMessageContaining('Something went wrong'); $this->rpc ->shouldReceive('call') @@ -139,13 +139,12 @@ public function testServiceShouldBeTerminated(): void }) ->andReturn(new Response(['ok' => true])); - $this->assertTrue($this->manager->terminate('foo')); + Assert::true($this->manager->terminate('foo')); } public function testServiceTerminateWithErrorsShouldThrowAnException(): void { - $this->expectException(ServiceException::class); - $this->expectExceptionMessage('Something went wrong'); + Expect::exception(ServiceException::class)->withMessageContaining('Something went wrong'); $this->rpc ->shouldReceive('call') @@ -187,7 +186,7 @@ public function testServiceStatusesShouldBeReturned(): void $status = $this->manager->statuses('foo'); - $this->assertSame([ + Assert::same($status, [ [ 'cpu_percent' => 59.5, 'pid' => 33, @@ -201,13 +200,12 @@ public function testServiceStatusesShouldBeReturned(): void ], ], ], - ], $status); + ]); } + #[BeforeTest] protected function setUp(): void { - parent::setUp(); - $this->rpc = m::mock(RPCInterface::class); $this->rpc diff --git a/tests/TestCase.php b/tests/TestCase.php deleted file mode 100644 index bd03acd..0000000 --- a/tests/TestCase.php +++ /dev/null @@ -1,9 +0,0 @@ -