Skip to content

Commit 9d555c8

Browse files
authored
Merge pull request #118 from altendky/fixture_order
trade concurrency for correct order
2 parents ff55152 + 40a9931 commit 9d555c8

File tree

2 files changed

+27
-48
lines changed

2 files changed

+27
-48
lines changed

pytest_twisted.py

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ class _instances:
5050
reactor = None
5151

5252

53-
class _tracking:
54-
async_yield_fixture_cache = {}
55-
to_be_torn_down = []
56-
57-
5853
def _deprecate(deprecated, recommended):
5954
def decorator(f):
6055
@functools.wraps(f)
@@ -282,6 +277,16 @@ def pytest_fixture_setup(fixturedef, request):
282277
return not None
283278

284279

280+
def _create_async_yield_fixture_finalizer(coroutine):
281+
def finalizer():
282+
_run_inline_callbacks(
283+
_tear_it_down,
284+
defer.ensureDeferred(coroutine.__anext__()),
285+
)
286+
287+
return finalizer
288+
289+
285290
@defer.inlineCallbacks
286291
def _async_pytest_fixture_setup(fixturedef, request, mark):
287292
"""Setup an async or async yield fixture."""
@@ -299,15 +304,11 @@ def _async_pytest_fixture_setup(fixturedef, request, mark):
299304
elif mark == 'async_yield_fixture':
300305
coroutine = fixture_function(**kwargs)
301306

302-
finalizer = functools.partial(
303-
_tracking.to_be_torn_down.append,
304-
coroutine,
307+
request.addfinalizer(
308+
_create_async_yield_fixture_finalizer(coroutine=coroutine),
305309
)
306-
request.addfinalizer(finalizer)
307310

308-
arg_value = yield defer.ensureDeferred(
309-
coroutine.__anext__(),
310-
)
311+
arg_value = yield defer.ensureDeferred(coroutine.__anext__())
311312
else:
312313
raise UnrecognizedCoroutineMarkError.from_mark(mark=mark)
313314

@@ -348,22 +349,6 @@ def in_reactor(d, f, *args):
348349
blockingCallFromThread(_instances.reactor, f, *args)
349350

350351

351-
@pytest.hookimpl(hookwrapper=True)
352-
def pytest_runtest_teardown(item):
353-
"""Tear down collected async yield fixtures."""
354-
yield
355-
356-
deferreds = []
357-
while len(_tracking.to_be_torn_down) > 0:
358-
coroutine = _tracking.to_be_torn_down.pop(0)
359-
deferred = defer.ensureDeferred(coroutine.__anext__())
360-
361-
deferreds.append(deferred)
362-
363-
for deferred in deferreds:
364-
_run_inline_callbacks(_tear_it_down, deferred)
365-
366-
367352
def pytest_pyfunc_call(pyfuncitem):
368353
"""Interface to async test call handler."""
369354
# TODO: only handle 'our' tests? what is the point of handling others?

testing/test_basic.py

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -413,40 +413,34 @@ def test_is_function_scope(scope):
413413

414414

415415
@skip_if_no_async_generators()
416-
def test_async_yield_fixture_concurrent_teardown(testdir, cmd_opts):
416+
def test_async_yield_fixture_ordered_teardown(testdir, cmd_opts):
417417
test_file = """
418418
from twisted.internet import reactor, defer
419419
import pytest
420420
import pytest_twisted
421421
422422
423-
here = defer.Deferred()
424-
there = defer.Deferred()
423+
results = []
425424
426-
@pytest_twisted.async_yield_fixture()
427-
async def this():
425+
@pytest.fixture(scope='function')
426+
def sync_fixture():
428427
yield 42
428+
results.append(2)
429429
430-
there.callback(None)
431-
reactor.callLater(5, here.cancel)
432-
await here
433-
434-
@pytest_twisted.async_yield_fixture()
435-
async def that():
436-
yield 37
430+
@pytest_twisted.async_yield_fixture(scope='function')
431+
async def async_fixture(sync_fixture):
432+
yield sync_fixture
433+
results.append(1)
437434
438-
here.callback(None)
439-
reactor.callLater(5, there.cancel)
440-
await there
435+
def test_first(async_fixture):
436+
assert async_fixture == 42
441437
442-
def test_succeed(this, that):
443-
pass
438+
def test_second():
439+
assert results == [1, 2]
444440
"""
445441
testdir.makepyfile(test_file)
446-
# TODO: add a timeout, failure just hangs indefinitely for now
447-
# https://github.com/pytest-dev/pytest/issues/4073
448442
rr = testdir.run(*cmd_opts, timeout=timeout)
449-
assert_outcomes(rr, {"passed": 1})
443+
assert_outcomes(rr, {"passed": 2})
450444

451445

452446
@skip_if_no_async_generators()

0 commit comments

Comments
 (0)