Skip to content

Commit

Permalink
Add setUpAsync() and tearDownAsync() (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
trowski committed May 1, 2020
1 parent 2e0a022 commit 99db640
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 9 deletions.
14 changes: 6 additions & 8 deletions .travis.yml
@@ -1,18 +1,16 @@
sudo: false
os: linux

language: php

php:
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4snapshot
- 7.4
- nightly

matrix:
jobs:
allow_failures:
- php: 7.4snapshot
- php: nightly
fast_finish: true

Expand All @@ -21,15 +19,15 @@ env:

install:
- composer update -n --prefer-dist
- wget https://github.com/php-coveralls/php-coveralls/releases/download/v1.0.2/coveralls.phar
- chmod +x coveralls.phar

script:
- vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml
- PHP_CS_FIXER_IGNORE_ENV=1 php vendor/bin/php-cs-fixer --diff --dry-run -v fix

after_script:
- ./coveralls.phar -v
- wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.2.0/php-coveralls.phar
- chmod +x php-coveralls.phar
- travis_retry ./php-coveralls.phar -v

cache:
directories:
Expand Down
1 change: 1 addition & 0 deletions composer.json
Expand Up @@ -18,6 +18,7 @@
"irc": "irc://irc.freenode.org/amphp"
},
"require": {
"php": ">=7.1",
"phpunit/phpunit": "^6 | ^7 | ^8 | ^9"
},
"require-dev": {
Expand Down
53 changes: 52 additions & 1 deletion src/AsyncTestCase.php
Expand Up @@ -56,7 +56,7 @@ final public function runAsyncTest(...$args)
$start = \microtime(true);

Loop::run(function () use (&$returnValue, &$exception, &$invoked, $args) {
$promise = $this->call([$this, $this->realTestName], ...$args);
$promise = new Coroutine($this->runAsyncTestCycle($args));
$promise->onResolve(function ($error, $value) use (&$invoked, &$exception, &$returnValue) {
$invoked = true;
$exception = $error;
Expand Down Expand Up @@ -91,12 +91,63 @@ final public function runAsyncTest(...$args)
return $returnValue;
}

private function runAsyncTestCycle(array $args): \Generator
{
try {
yield $this->call(\Closure::fromCallable([$this, 'setUpAsync']));
} catch (\Throwable $exception) {
throw new \Error(\sprintf(
'%s::setUpAsync() failed',
\str_replace("\0", '@', \get_class($this)) // replace NUL-byte in anonymous class name
), 0, $exception);
}

try {
$returnValue = yield $this->call([$this, $this->realTestName], ...$args);
} catch (\Throwable $testException) {
// Exception rethrown in finally block below
}

try {
yield $this->call(\Closure::fromCallable([$this, 'tearDownAsync']));
} catch (\Throwable $exception) {
throw new \Error(\sprintf(
'%s::tearDownAsync() failed',
\str_replace("\0", '@', \get_class($this)) // replace NUL-byte in anonymous class name
), 0, $exception);
} finally {
if (isset($testException)) {
throw $testException;
}
}

return $returnValue;
}

final protected function runTest()
{
parent::setName('runAsyncTest');
return parent::runTest();
}

/**
* Called before each test. Similar to {@see TestCase::setUp()}, except the method may return a promise or
* coroutine (@see \Amp\call()} that will be awaited before executing the test.
*/
protected function setUpAsync()
{
// Empty method to be overloaded by inheriting class if desired.
}

/**
* Called after each test. Similar to {@see TestCase::tearDown()}, except the method may return a promise or
* coroutine (@see \Amp\call()} that will be awaited before executing the next test.
*/
protected function tearDownAsync()
{
// Empty method to be overloaded by inheriting class if desired.
}

/**
* Fails the test if the loop does not run for at least the given amount of time.
*
Expand Down
17 changes: 17 additions & 0 deletions test/AsyncTestCaseTest.php
Expand Up @@ -42,6 +42,13 @@ public function testThatWeHandleNotPromiseReturned(): \Generator
$this->assertTrue($testData->val, 'Expected our test to run on loop to completion');
}

public function testReturningPromise(): Promise
{
$returnValue = new Delayed(100, 'value');
$this->assertInstanceOf(Promise::class, $returnValue); // An assertion is required for the test to pass
return $returnValue; // Return value used by testReturnValueFromDependentTest
}

public function testExpectingAnExceptionThrown(): \Generator
{
$throwException = function () {
Expand Down Expand Up @@ -97,6 +104,16 @@ public function testArgumentSupport(string $foo, int $bar, bool $baz)
$this->assertTrue($baz);
}

/**
* @param string|null $value
*
* @depends testReturningPromise
*/
public function testReturnValueFromDependentTest(string $value = null)
{
$this->assertSame('value', $value);
}

public function testSetTimeout(): \Generator
{
$this->setTimeout(100);
Expand Down
54 changes: 54 additions & 0 deletions test/AsyncTestCaseWithSetUpAndTearDownTest.php
@@ -0,0 +1,54 @@
<?php

namespace Amp\PHPUnit\Test;

use Amp\Failure;
use Amp\PHPUnit\AsyncTestCase;
use Amp\PHPUnit\TestException;
use Amp\Promise;
use Amp\Success;

class AsyncTestCaseWithSetUpAndTearDownTest extends AsyncTestCase
{
protected function setUpAsync(): Promise
{
if ($this->getName() === 'testFailingSetUpAsync') {
$this->expectException(\Error::class);
$this->expectExceptionMessage('setUpAsync() failed');

return new Failure(new TestException);
}

return new Success;
}

protected function tearDownAsync(): Promise
{
if ($this->getName() === 'testFailingTearDownAsync') {
$this->expectException(\Error::class);
$this->expectExceptionMessage('tearDownAsync() failed');

return new Failure(new TestException);
}

return new Success;
}

public function testExpectedException(): void
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Test exception');

throw new \Exception('Test exception');
}

public function testFailingTearDownAsync()
{
// Expected exception set in tearDownAsync().
}

public function testFailingSetUpAsync()
{
// Expected exception set in setUpAsync().
}
}

0 comments on commit 99db640

Please sign in to comment.