diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index 45952c3..4c64dd8 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -4,13 +4,17 @@ on: pull_request: null push: branches: - - main + - master jobs: code_analysis: strategy: fail-fast: false matrix: + php: + - "8.1" + - "8.2" + - "8.3" actions: - name: "PHPStan" @@ -20,19 +24,19 @@ jobs: name: "PHPUnit" run: vendor/bin/phpunit - name: ${{ matrix.actions.name }} + name: PHP${{ matrix.php }}:${{ matrix.actions.name }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # see https://github.com/shivammathur/setup-php - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: ${{ matrix.php }}) coverage: none # composer install cache - https://github.com/ramsey/composer-install - - uses: "ramsey/composer-install@v1" + - uses: "ramsey/composer-install@v2" - run: ${{ matrix.actions.run }} diff --git a/.gitignore b/.gitignore index 47342dc..323486b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ composer.lock vendor/ .phpunit.result.cache +.phpunit.cache diff --git a/composer.json b/composer.json index 06b2e00..912a2ab 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,11 @@ "description": "Library for asserting things that happen asynchronously with PHPUnit", "license": "MIT", "type": "library", - "keywords": ["PHPUnit", "asynchronicity", "assertion"], + "keywords": [ + "PHPUnit", + "asynchronicity", + "assertion" + ], "authors": [ { "name": "Matthias Noback", @@ -22,10 +26,11 @@ } }, "require": { - "php": "^7.3 || ^8.0" + "php": "^8.1" }, "require-dev": { - "phpstan/phpstan": "^0.9.2", - "phpunit/phpunit": "^9.0" + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.0", + "ext-pcntl": "*" } -} +} \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon index 1494f51..47d35e5 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,3 +3,4 @@ parameters: paths: - src - tests + ignoreErrors: [] diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b5974e8..25c3806 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,17 +1,18 @@ - - - - ./tests - - - - - ./ - - ./tests - ./vendor - - - + + + + + ./tests + + + + + ./ + + + ./tests + ./vendor + + diff --git a/src/Asynchronicity/PHPUnit/Eventually.php b/src/Asynchronicity/PHPUnit/Eventually.php index dee05bc..9f0f7e4 100644 --- a/src/Asynchronicity/PHPUnit/Eventually.php +++ b/src/Asynchronicity/PHPUnit/Eventually.php @@ -3,6 +3,7 @@ namespace Asynchronicity\PHPUnit; +use Asynchronicity\Polling\IncorrectUsage; use Asynchronicity\Polling\Interrupted; use Asynchronicity\Polling\Poller; use Asynchronicity\Polling\SystemClock; @@ -11,8 +12,8 @@ final class Eventually extends Constraint { - private $timeoutMilliseconds; - private $waitMilliseconds; + private int $timeoutMilliseconds; + private int $waitMilliseconds; public function __construct(int $timeoutMilliseconds = 5000, int $waitMilliseconds = 500) { @@ -20,8 +21,15 @@ public function __construct(int $timeoutMilliseconds = 5000, int $waitMillisecon $this->waitMilliseconds = $waitMilliseconds; } - public function evaluate($probe, string $description = '', bool $returnResult = false): ?bool + /** + * @throws Interrupted + */ + public function evaluate(mixed $probe, string $description = '', bool $returnResult = false): ?bool { + if (!is_callable($probe)) { + throw new IncorrectUsage(); + } + try { $poller = new Poller(); $poller->poll( @@ -39,13 +47,13 @@ public function evaluate($probe, string $description = '', bool $returnResult = return true; } - protected function failureDescription($other): string + protected function failureDescription(mixed $other): string { return 'the given probe was satisfied within the provided timeout'; } public function toString(): string { - throw new \BadMethodCallException('Not implemented'); + return 'Eventually'; } -} +} \ No newline at end of file diff --git a/tests/Asynchronicity/PHPUnit/EventuallyTest.php b/tests/Asynchronicity/PHPUnit/EventuallyTest.php index 36aa343..4f9df66 100644 --- a/tests/Asynchronicity/PHPUnit/EventuallyTest.php +++ b/tests/Asynchronicity/PHPUnit/EventuallyTest.php @@ -10,10 +10,7 @@ final class EventuallyTest extends TestCase { - /** - * @var Eventually - */ - private $constraint; + private Eventually $constraint; /** * @var callable @@ -101,6 +98,27 @@ public function it_accepts_a_closure_as_probe(): void })); } + /** + * @test + */ + public function it_throws_an_exception_if_the_probe_is_not_callable(): void + { + $constraint = new Eventually(); + + $this->expectException(IncorrectUsage::class); + $constraint->evaluate('foobar'); + } + + /** + * @test + */ + public function it_is_stringable(): void + { + $constraint = new Eventually(); + + $this->assertSame('Eventually', $constraint->toString()); + } + private function probeAlwaysFails(): void { $this->probe = function (): void { diff --git a/tests/Asynchronicity/PHPUnit/FileHasBeenCreated.php b/tests/Asynchronicity/PHPUnit/FileHasBeenCreated.php index 562a9a9..a48fa90 100644 --- a/tests/Asynchronicity/PHPUnit/FileHasBeenCreated.php +++ b/tests/Asynchronicity/PHPUnit/FileHasBeenCreated.php @@ -7,7 +7,7 @@ final class FileHasBeenCreated { - private $path; + private string $path; public function __construct(string $path) { diff --git a/tests/Asynchronicity/PHPUnit/IntegrationTest.php b/tests/Asynchronicity/PHPUnit/IntegrationTest.php index 53de78b..46ff095 100644 --- a/tests/Asynchronicity/PHPUnit/IntegrationTest.php +++ b/tests/Asynchronicity/PHPUnit/IntegrationTest.php @@ -15,14 +15,14 @@ final class IntegrationTest extends TestCase public function it_waits_until_a_child_process_does_something(): void { if (!\extension_loaded('pcntl')) { - $this->markTestSkipped('Requires PCNTL extension'); + self::markTestSkipped('Requires PCNTL extension'); } $timeoutMilliseconds = 2000; $waitMilliseconds = 1000; $file = sys_get_temp_dir().'/'.uniqid('phpunit-asynchronicity', true); - $this->assertFileNotExists($file); + self::assertFileDoesNotExist($file); $pid = pcntl_fork(); if ($pid === -1) { diff --git a/tests/Asynchronicity/Polling/PollerTest.php b/tests/Asynchronicity/Polling/PollerTest.php index 7a6e757..44f1561 100644 --- a/tests/Asynchronicity/Polling/PollerTest.php +++ b/tests/Asynchronicity/Polling/PollerTest.php @@ -4,11 +4,12 @@ namespace Asynchronicity\Polling; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; final class PollerTest extends TestCase { - private $waitTimeInMilliseconds = 1000; + private int $waitTimeInMilliseconds = 1000; /** * @var callable @@ -21,7 +22,7 @@ final class PollerTest extends TestCase private $poller; /** - * @var Clock + * @var Clock&MockObject */ private $clock; diff --git a/tests/Asynchronicity/Polling/TimeoutTest.php b/tests/Asynchronicity/Polling/TimeoutTest.php index 99779d3..56f214d 100644 --- a/tests/Asynchronicity/Polling/TimeoutTest.php +++ b/tests/Asynchronicity/Polling/TimeoutTest.php @@ -14,7 +14,7 @@ final class TimeoutTest extends TestCase private $timeout; /** - * @var MockObject & Clock + * @var MockObject&Clock */ private $clock; @@ -86,20 +86,14 @@ public function it_fails_when_start_is_not_called_first(): void $this->timeout->hasTimedOut(); } + /** + * @param int[] $microtimes + */ private function clockReturnsMicrotimes(array $microtimes): void { - static $at; - if ($at === null) { - $at = 0; - } - - foreach ($microtimes as $microtime) { - $this->clock - ->expects($this->at($at)) - ->method('getMicrotime') - ->will($this->returnValue($microtime)); - - $at++; - } + $this->clock + ->expects($this->exactly(count($microtimes))) + ->method('getMicrotime') + ->willReturnOnConsecutiveCalls(...$microtimes); } }