Skip to content

Commit 681fa3d

Browse files
authored
Merge pull request #34 from altendky/31-altendky-async_callbacks
[31] Add @ensureDeferred for use with async/await
2 parents a9ed941 + 555edc9 commit 681fa3d

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

README.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ is to ``import pytest_twisted as pt``.
5151

5252

5353
inlineCallbacks
54-
=================
54+
===============
5555
Using ``twisted.internet.defer.inlineCallbacks`` as a decorator for test
5656
functions, which take funcargs, does not work. Please use
5757
``pytest_twisted.inlineCallbacks`` instead::
@@ -61,6 +61,19 @@ functions, which take funcargs, does not work. Please use
6161
res = yield threads.deferToThread(os.listdir, tmpdir.strpath)
6262
assert res == []
6363

64+
65+
ensureDeferred
66+
==============
67+
Using ``twisted.internet.defer.ensureDeferred`` as a decorator for test
68+
functions, which take funcargs, does not work. Please use
69+
``pytest_twisted.ensureDeferred`` instead::
70+
71+
@pytest_twisted.ensureDeferred
72+
async def test_some_stuff(tmpdir):
73+
res = await threads.deferToThread(os.listdir, tmpdir.strpath)
74+
assert res == []
75+
76+
6477
Waiting for deferreds in fixtures
6578
=================================
6679
``pytest_twisted.blockon`` allows fixtures to wait for deferreds::

pytest_twisted.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ def inlineCallbacks(fun, *args, **kw):
6161
return defer.inlineCallbacks(fun)(*args, **kw)
6262

6363

64+
@decorator.decorator
65+
def ensureDeferred(fun, *args, **kw):
66+
return defer.ensureDeferred(fun(*args, **kw))
67+
68+
6469
def init_twisted_greenlet():
6570
if _instances.reactor is None or _instances.gr_twisted:
6671
return

testing/test_basic.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33

44
import pytest
55

6+
import pytest_twisted
7+
8+
9+
ASYNC_AWAIT = sys.version_info >= (3, 5)
10+
611

712
def assert_outcomes(run_result, outcomes):
813
formatted_output = format_run_result_output_for_assert(run_result)
@@ -35,6 +40,13 @@ def skip_if_reactor_not(request, expected_reactor):
3540
pytest.skip("reactor is {} not {}".format(actual_reactor, expected_reactor))
3641

3742

43+
def skip_if_no_async_await():
44+
return pytest.mark.skipif(
45+
not ASYNC_AWAIT,
46+
reason="async/await syntax not supported on Python <3.5",
47+
)
48+
49+
3850
@pytest.fixture
3951
def cmd_opts(request):
4052
reactor = request.config.getoption("reactor", "default")
@@ -126,6 +138,28 @@ def test_succeed(foo):
126138
assert_outcomes(rr, {"passed": 2, "failed": 1})
127139

128140

141+
@skip_if_no_async_await()
142+
def test_async_await(testdir, cmd_opts):
143+
test_file = """
144+
from twisted.internet import reactor, defer
145+
import pytest
146+
import pytest_twisted
147+
148+
@pytest.fixture(scope="module", params=["fs", "imap", "web"])
149+
def foo(request):
150+
return request.param
151+
152+
@pytest_twisted.ensureDeferred
153+
async def test_succeed(foo):
154+
await defer.succeed(foo)
155+
if foo == "web":
156+
raise RuntimeError("baz")
157+
"""
158+
testdir.makepyfile(test_file)
159+
rr = testdir.run(sys.executable, "-m", "pytest", "-v", *cmd_opts)
160+
assert_outcomes(rr, {"passed": 2, "failed": 1})
161+
162+
129163
def test_twisted_greenlet(testdir, cmd_opts):
130164
test_file = """
131165
import pytest, greenlet
@@ -171,6 +205,32 @@ def test_succeed(foo):
171205
assert_outcomes(rr, {"passed": 2, "failed": 1})
172206

173207

208+
@skip_if_no_async_await()
209+
def test_blockon_in_fixture_async(testdir, cmd_opts):
210+
test_file = """
211+
from twisted.internet import reactor, defer
212+
import pytest
213+
import pytest_twisted
214+
215+
@pytest.fixture(scope="module", params=["fs", "imap", "web"])
216+
def foo(request):
217+
d1, d2 = defer.Deferred(), defer.Deferred()
218+
reactor.callLater(0.01, d1.callback, 1)
219+
reactor.callLater(0.02, d2.callback, request.param)
220+
pytest_twisted.blockon(d1)
221+
return d2
222+
223+
@pytest_twisted.ensureDeferred
224+
async def test_succeed(foo):
225+
x = await foo
226+
if x == "web":
227+
raise RuntimeError("baz")
228+
"""
229+
testdir.makepyfile(test_file)
230+
rr = testdir.run(sys.executable, "-m", "pytest", "-v", *cmd_opts)
231+
assert_outcomes(rr, {"passed": 2, "failed": 1})
232+
233+
174234
def test_blockon_in_hook(testdir, cmd_opts, request):
175235
skip_if_reactor_not(request, "default")
176236
conftest_file = """

0 commit comments

Comments
 (0)