Skip to content

Commit 99db640

Browse files
authored
Add setUpAsync() and tearDownAsync() (#17)
1 parent 2e0a022 commit 99db640

File tree

5 files changed

+130
-9
lines changed

5 files changed

+130
-9
lines changed

.travis.yml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
sudo: false
1+
os: linux
22

33
language: php
44

55
php:
6-
- 7.0
76
- 7.1
87
- 7.2
98
- 7.3
10-
- 7.4snapshot
9+
- 7.4
1110
- nightly
1211

13-
matrix:
12+
jobs:
1413
allow_failures:
15-
- php: 7.4snapshot
1614
- php: nightly
1715
fast_finish: true
1816

@@ -21,15 +19,15 @@ env:
2119

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

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

3127
after_script:
32-
- ./coveralls.phar -v
28+
- wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.2.0/php-coveralls.phar
29+
- chmod +x php-coveralls.phar
30+
- travis_retry ./php-coveralls.phar -v
3331

3432
cache:
3533
directories:

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"irc": "irc://irc.freenode.org/amphp"
1919
},
2020
"require": {
21+
"php": ">=7.1",
2122
"phpunit/phpunit": "^6 | ^7 | ^8 | ^9"
2223
},
2324
"require-dev": {

src/AsyncTestCase.php

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ final public function runAsyncTest(...$args)
5656
$start = \microtime(true);
5757

5858
Loop::run(function () use (&$returnValue, &$exception, &$invoked, $args) {
59-
$promise = $this->call([$this, $this->realTestName], ...$args);
59+
$promise = new Coroutine($this->runAsyncTestCycle($args));
6060
$promise->onResolve(function ($error, $value) use (&$invoked, &$exception, &$returnValue) {
6161
$invoked = true;
6262
$exception = $error;
@@ -91,12 +91,63 @@ final public function runAsyncTest(...$args)
9191
return $returnValue;
9292
}
9393

94+
private function runAsyncTestCycle(array $args): \Generator
95+
{
96+
try {
97+
yield $this->call(\Closure::fromCallable([$this, 'setUpAsync']));
98+
} catch (\Throwable $exception) {
99+
throw new \Error(\sprintf(
100+
'%s::setUpAsync() failed',
101+
\str_replace("\0", '@', \get_class($this)) // replace NUL-byte in anonymous class name
102+
), 0, $exception);
103+
}
104+
105+
try {
106+
$returnValue = yield $this->call([$this, $this->realTestName], ...$args);
107+
} catch (\Throwable $testException) {
108+
// Exception rethrown in finally block below
109+
}
110+
111+
try {
112+
yield $this->call(\Closure::fromCallable([$this, 'tearDownAsync']));
113+
} catch (\Throwable $exception) {
114+
throw new \Error(\sprintf(
115+
'%s::tearDownAsync() failed',
116+
\str_replace("\0", '@', \get_class($this)) // replace NUL-byte in anonymous class name
117+
), 0, $exception);
118+
} finally {
119+
if (isset($testException)) {
120+
throw $testException;
121+
}
122+
}
123+
124+
return $returnValue;
125+
}
126+
94127
final protected function runTest()
95128
{
96129
parent::setName('runAsyncTest');
97130
return parent::runTest();
98131
}
99132

133+
/**
134+
* Called before each test. Similar to {@see TestCase::setUp()}, except the method may return a promise or
135+
* coroutine (@see \Amp\call()} that will be awaited before executing the test.
136+
*/
137+
protected function setUpAsync()
138+
{
139+
// Empty method to be overloaded by inheriting class if desired.
140+
}
141+
142+
/**
143+
* Called after each test. Similar to {@see TestCase::tearDown()}, except the method may return a promise or
144+
* coroutine (@see \Amp\call()} that will be awaited before executing the next test.
145+
*/
146+
protected function tearDownAsync()
147+
{
148+
// Empty method to be overloaded by inheriting class if desired.
149+
}
150+
100151
/**
101152
* Fails the test if the loop does not run for at least the given amount of time.
102153
*

test/AsyncTestCaseTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ public function testThatWeHandleNotPromiseReturned(): \Generator
4242
$this->assertTrue($testData->val, 'Expected our test to run on loop to completion');
4343
}
4444

45+
public function testReturningPromise(): Promise
46+
{
47+
$returnValue = new Delayed(100, 'value');
48+
$this->assertInstanceOf(Promise::class, $returnValue); // An assertion is required for the test to pass
49+
return $returnValue; // Return value used by testReturnValueFromDependentTest
50+
}
51+
4552
public function testExpectingAnExceptionThrown(): \Generator
4653
{
4754
$throwException = function () {
@@ -97,6 +104,16 @@ public function testArgumentSupport(string $foo, int $bar, bool $baz)
97104
$this->assertTrue($baz);
98105
}
99106

107+
/**
108+
* @param string|null $value
109+
*
110+
* @depends testReturningPromise
111+
*/
112+
public function testReturnValueFromDependentTest(string $value = null)
113+
{
114+
$this->assertSame('value', $value);
115+
}
116+
100117
public function testSetTimeout(): \Generator
101118
{
102119
$this->setTimeout(100);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace Amp\PHPUnit\Test;
4+
5+
use Amp\Failure;
6+
use Amp\PHPUnit\AsyncTestCase;
7+
use Amp\PHPUnit\TestException;
8+
use Amp\Promise;
9+
use Amp\Success;
10+
11+
class AsyncTestCaseWithSetUpAndTearDownTest extends AsyncTestCase
12+
{
13+
protected function setUpAsync(): Promise
14+
{
15+
if ($this->getName() === 'testFailingSetUpAsync') {
16+
$this->expectException(\Error::class);
17+
$this->expectExceptionMessage('setUpAsync() failed');
18+
19+
return new Failure(new TestException);
20+
}
21+
22+
return new Success;
23+
}
24+
25+
protected function tearDownAsync(): Promise
26+
{
27+
if ($this->getName() === 'testFailingTearDownAsync') {
28+
$this->expectException(\Error::class);
29+
$this->expectExceptionMessage('tearDownAsync() failed');
30+
31+
return new Failure(new TestException);
32+
}
33+
34+
return new Success;
35+
}
36+
37+
public function testExpectedException(): void
38+
{
39+
$this->expectException(\Exception::class);
40+
$this->expectExceptionMessage('Test exception');
41+
42+
throw new \Exception('Test exception');
43+
}
44+
45+
public function testFailingTearDownAsync()
46+
{
47+
// Expected exception set in tearDownAsync().
48+
}
49+
50+
public function testFailingSetUpAsync()
51+
{
52+
// Expected exception set in setUpAsync().
53+
}
54+
}

0 commit comments

Comments
 (0)