diff --git a/.github/workflows/isolated-tests.yml b/.github/workflows/isolated-tests.yml index f60f308f5..3148398cb 100644 --- a/.github/workflows/isolated-tests.yml +++ b/.github/workflows/isolated-tests.yml @@ -61,6 +61,10 @@ jobs: extensions: dom, curl, libxml, mbstring, pcntl, fileinfo, intl coverage: pcov + - name: Setup Redis + if: ${{ matrix.os != 'windows-latest' && matrix.package.name == 'kv-store' }} + uses: supercharge/redis-github-action@1.7.0 + - name: Install PHPUnit run: composer global require phpunit/phpunit:^12.2.3 diff --git a/packages/cryptography/tests/Encryption/EncryptionTest.php b/packages/cryptography/tests/Encryption/EncryptionTest.php index b7e55288f..a503b5727 100644 --- a/packages/cryptography/tests/Encryption/EncryptionTest.php +++ b/packages/cryptography/tests/Encryption/EncryptionTest.php @@ -62,7 +62,7 @@ public function test_time_protection(): void $this->assertSame('important data', $encrypter->decrypt($encrypted)); $elapsed = microtime(true) - $start; - $this->assertEqualsToMoreOrLess(0.3, $elapsed, margin: 0.015); + $this->assertEqualsToMoreOrLess(0.3, $elapsed, margin: 0.020, windowsMargin: 0.025); } public function test_wrong_key(): void diff --git a/packages/cryptography/tests/HasMoreIntegerAssertions.php b/packages/cryptography/tests/HasMoreIntegerAssertions.php index 71eb317d9..3c0958794 100644 --- a/packages/cryptography/tests/HasMoreIntegerAssertions.php +++ b/packages/cryptography/tests/HasMoreIntegerAssertions.php @@ -6,8 +6,12 @@ trait HasMoreIntegerAssertions { - private function assertEqualsToMoreOrLess(int|float $expected, int|float $actual, int|float $margin): void + private function assertEqualsToMoreOrLess(int|float $expected, int|float $actual, int|float $margin, null|int|float $windowsMargin = null): void { + if ($windowsMargin && PHP_OS_FAMILY === 'Windows') { + $margin = $windowsMargin; + } + try { $this->assertGreaterThanOrEqual($expected - $margin, $actual); $this->assertLessThanOrEqual($expected + $margin, $actual); diff --git a/packages/cryptography/tests/Signing/SignerTest.php b/packages/cryptography/tests/Signing/SignerTest.php index e51a2a18f..ed8ea6ee5 100644 --- a/packages/cryptography/tests/Signing/SignerTest.php +++ b/packages/cryptography/tests/Signing/SignerTest.php @@ -166,7 +166,7 @@ public function test_time_protection(): void $this->assertTrue($signer->verify($data, $signature)); $elapsed = microtime(true) - $start; - $this->assertEqualsToMoreOrLess(0.3, $elapsed, margin: 0.015); + $this->assertEqualsToMoreOrLess(0.3, $elapsed, margin: 0.015, windowsMargin: 0.025); } public function test_time_protection_with_mock_clock(): void diff --git a/packages/cryptography/tests/TimelockTest.php b/packages/cryptography/tests/TimelockTest.php index 848d18ac7..520960e9f 100644 --- a/packages/cryptography/tests/TimelockTest.php +++ b/packages/cryptography/tests/TimelockTest.php @@ -31,7 +31,7 @@ public function test_locks_for_duration(): void $elapsed = microtime(true) - $start; - $this->assertEqualsToMoreOrLess(0.1, $elapsed, margin: 0.015); + $this->assertEqualsToMoreOrLess(0.1, $elapsed, margin: 0.015, windowsMargin: 0.025); } public function test_return_early(): void @@ -63,7 +63,7 @@ public function test_throws_exception_after_delay(): void ); } catch (\RuntimeException) { $elapsed = microtime(true) - $start; - $this->assertEqualsToMoreOrLess(0.1, $elapsed, margin: 0.015); + $this->assertEqualsToMoreOrLess(0.1, $elapsed, margin: 0.015, windowsMargin: 0.025); } } diff --git a/packages/kv-store/composer.json b/packages/kv-store/composer.json index 6ae70df77..629555509 100644 --- a/packages/kv-store/composer.json +++ b/packages/kv-store/composer.json @@ -6,6 +6,7 @@ "require": { "php": "^8.4", "tempest/support": "dev-main", + "tempest/datetime": "dev-main", "tempest/event-bus": "dev-main" }, "require-dev": { diff --git a/packages/kv-store/tests/PhpRedisClientTest.php b/packages/kv-store/tests/PhpRedisClientTest.php index c1baa650b..d79b645bf 100644 --- a/packages/kv-store/tests/PhpRedisClientTest.php +++ b/packages/kv-store/tests/PhpRedisClientTest.php @@ -2,22 +2,22 @@ namespace Tempest\KeyValue\Tests; +use PHPUnit\Framework\Attributes\PostCondition; +use PHPUnit\Framework\Attributes\PreCondition; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Tempest\KeyValue\Redis\Config\RedisConfig; use Tempest\KeyValue\Redis\PhpRedisClient; +use Throwable; +#[RequiresPhpExtension('redis')] final class PhpRedisClientTest extends TestCase { private PhpRedisClient $redis; - protected function setUp(): void + #[PreCondition] + protected function configure(): void { - parent::setUp(); - - if (! extension_loaded('redis') || ! class_exists(\Redis::class)) { - $this->markTestSkipped('The `redis` extension is not loaded.'); - } - $this->redis = new PhpRedisClient( client: new \Redis(), config: new RedisConfig( @@ -29,17 +29,17 @@ protected function setUp(): void try { $this->redis->connect(); - } catch (\Throwable) { + } catch (Throwable) { $this->markTestSkipped('Could not connect to Redis.'); } } - protected function tearDown(): void + #[PostCondition] + protected function cleanup(): void { try { $this->redis->flush(); - } finally { - parent::tearDown(); + } catch (Throwable) { } } diff --git a/packages/kv-store/tests/PredisClientTest.php b/packages/kv-store/tests/PredisClientTest.php index 0d876d032..721586052 100644 --- a/packages/kv-store/tests/PredisClientTest.php +++ b/packages/kv-store/tests/PredisClientTest.php @@ -2,19 +2,20 @@ namespace Tempest\KeyValue\Tests; +use PHPUnit\Framework\Attributes\PostCondition; +use PHPUnit\Framework\Attributes\PreCondition; use PHPUnit\Framework\TestCase; use Predis; -use Tempest\KeyValue\Redis\PhpRedisClient; use Tempest\KeyValue\Redis\PredisClient; +use Throwable; final class PredisClientTest extends TestCase { private PredisClient $redis; - protected function setUp(): void + #[PreCondition] + protected function configure(): void { - parent::setUp(); - if (! class_exists(Predis\Client::class)) { $this->markTestSkipped('The `predis/predis` package is not installed.'); } @@ -34,17 +35,17 @@ protected function setUp(): void try { $this->redis->connect(); - } catch (\Throwable) { + } catch (Throwable) { $this->markTestSkipped('Could not connect to Redis.'); } } - protected function tearDown(): void + #[PostCondition] + protected function cleanup(): void { try { $this->redis->flush(); - } finally { - parent::tearDown(); + } catch (Throwable) { } } diff --git a/packages/support/tests/Filesystem/UnixFunctionsTest.php b/packages/support/tests/Filesystem/UnixFunctionsTest.php index 47c88daf7..08563796e 100644 --- a/packages/support/tests/Filesystem/UnixFunctionsTest.php +++ b/packages/support/tests/Filesystem/UnixFunctionsTest.php @@ -2,6 +2,8 @@ namespace Tempest\Support\Tests\Filesystem; +use PHPUnit\Framework\Attributes\PostCondition; +use PHPUnit\Framework\Attributes\PreCondition; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Tempest\Support\Filesystem; @@ -17,12 +19,11 @@ final class UnixFunctionsTest extends TestCase { private string $fixtures = __DIR__ . '/Fixtures'; - protected function setUp(): void + #[PreCondition] + protected function configure(): void { - parent::setUp(); - if (PHP_OS_FAMILY === 'Windows') { - $this->markTestSkipped('Irrelevant on Windows.'); + $this->markTestSkipped('This test is only for Unix-like systems.'); } Filesystem\ensure_directory_empty($this->fixtures); @@ -30,9 +31,12 @@ protected function setUp(): void $this->assertTrue(is_dir($this->fixtures)); } - protected function tearDown(): void + #[PostCondition] + protected function cleanup(): void { - parent::tearDown(); + if (PHP_OS_FAMILY === 'Windows') { + return; + } Filesystem\delete_directory($this->fixtures); diff --git a/tests/Integration/KeyValue/RedisTest.php b/tests/Integration/KeyValue/RedisTest.php index db70faa23..23fab1ba5 100644 --- a/tests/Integration/KeyValue/RedisTest.php +++ b/tests/Integration/KeyValue/RedisTest.php @@ -2,19 +2,21 @@ namespace Tests\Tempest\Integration\KeyValue; +use PHPUnit\Framework\Attributes\PostCondition; +use PHPUnit\Framework\Attributes\PreCondition; use Tempest\KeyValue\Redis\Config\RedisConfig; use Tempest\KeyValue\Redis\Redis; use Tempest\KeyValue\Redis\RedisCommandExecuted; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; +use Throwable; final class RedisTest extends FrameworkIntegrationTestCase { private Redis $redis; - protected function setUp(): void + #[PreCondition] + protected function configure(): void { - parent::setUp(); - $this->eventBus->preventEventHandling(); $this->container->config(new RedisConfig( @@ -32,12 +34,12 @@ protected function setUp(): void } } - protected function tearDown(): void + #[PostCondition] + protected function cleanup(): void { try { $this->redis->flush(); - } finally { - parent::tearDown(); + } catch (Throwable) { } } diff --git a/tests/Integration/Mapper/PsrRequestToRequestMapperTest.php b/tests/Integration/Mapper/PsrRequestToRequestMapperTest.php index ecf98626c..37bd7fd3c 100644 --- a/tests/Integration/Mapper/PsrRequestToRequestMapperTest.php +++ b/tests/Integration/Mapper/PsrRequestToRequestMapperTest.php @@ -99,23 +99,18 @@ public function test_files(): void public function test_body_field_in_body(): void { - $psrRequest = $this->http->makePsrRequest( - '/', - Method::POST, - body: [ - 'body' => 'text', - ], + $request = new PsrRequestToGenericRequestMapper($this->encrypter)->map( + from: $this->http->makePsrRequest( + uri: '/', + body: [ + 'body' => 'text', + ], + ), + to: GenericRequest::class, ); - $mapper = new PsrRequestToGenericRequestMapper(); - - $request = $mapper->map($psrRequest, GenericRequest::class); - - $this->assertSame( - [ - 'body' => 'text', - ], - $request->body, - ); + $this->assertSame([ + 'body' => 'text', + ], $request->body); } }