Skip to content

Commit

Permalink
Fix #2565: Fix compatibility with pytest 3.3+
Browse files Browse the repository at this point in the history
  • Loading branch information
asvetlov committed Nov 29, 2017
1 parent 5577631 commit 893f0c9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 54 deletions.
1 change: 1 addition & 0 deletions CHANGES/2565.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix compatibility with `pytest` 3.3+
59 changes: 31 additions & 28 deletions aiohttp/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,13 @@ def finalizer():
@pytest.fixture
def fast(request):
""" --fast config option """
return request.config.getoption('--fast') # pragma: no cover
return request.config.getoption('--fast')


@pytest.fixture
def loop_debug(request):
""" --enable-loop-debug config option """
return request.config.getoption('--enable-loop-debug')


@contextlib.contextmanager
Expand Down Expand Up @@ -162,50 +168,47 @@ def pytest_pyfunc_call(pyfuncitem):
return True


def pytest_configure(config):
loops = config.getoption('--loop')
def pytest_generate_tests(metafunc):
if 'loop_factory' not in metafunc.fixturenames:
return

factories = {'pyloop': asyncio.new_event_loop}
loops = metafunc.config.option.loop
avail_factories = {'pyloop': asyncio.new_event_loop}

if uvloop is not None: # pragma: no cover
factories['uvloop'] = uvloop.new_event_loop
avail_factories['uvloop'] = uvloop.new_event_loop

if tokio is not None: # pragma: no cover
factories['tokio'] = tokio.new_event_loop

LOOP_FACTORIES.clear()
LOOP_FACTORY_IDS.clear()
avail_factories['tokio'] = tokio.new_event_loop

if loops == 'all':
loops = 'pyloop,uvloop?,tokio?'

factories = {}
for name in loops.split(','):
required = not name.endswith('?')
name = name.strip(' ?')
if name in factories:
LOOP_FACTORIES.append(factories[name])
LOOP_FACTORY_IDS.append(name)
elif required:
raise ValueError(
"Unknown loop '%s', available loops: %s" % (
name, list(factories.keys())))
asyncio.set_event_loop(None)
if name not in avail_factories:
if required:
raise ValueError(
"Unknown loop '%s', available loops: %s" % (
name, list(factories.keys())))
else:
continue
factories[name] = avail_factories[name]
metafunc.parametrize("loop_factory",
list(factories.values()),
ids=list(factories.keys()))


LOOP_FACTORIES = []
LOOP_FACTORY_IDS = []


@pytest.fixture(params=LOOP_FACTORIES, ids=LOOP_FACTORY_IDS)
def loop(request):
@pytest.fixture
def loop(loop_factory, fast, loop_debug):
"""Return an instance of the event loop."""
fast = request.config.getoption('--fast')
debug = request.config.getoption('--enable-loop-debug')

with loop_context(request.param, fast=fast) as _loop:
if debug:
with loop_context(loop_factory, fast=fast) as _loop:
if loop_debug:
_loop.set_debug(True) # pragma: no cover
yield _loop
asyncio.set_event_loop(None)


@pytest.fixture
Expand Down
42 changes: 16 additions & 26 deletions tests/test_pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

import pytest

from aiohttp.pytest_plugin import LOOP_FACTORIES


pytest_plugins = 'pytester'

CONFTEST = '''
pytest_plugins = 'aiohttp.pytest_plugin'
'''


def test_aiohttp_plugin(testdir):
testdir.makepyfile("""\
Expand All @@ -17,10 +19,6 @@ def test_aiohttp_plugin(testdir):
from aiohttp import web
pytest_plugins = 'aiohttp.pytest_plugin'
@asyncio.coroutine
def hello(request):
return web.Response(body=b'Hello, world')
Expand Down Expand Up @@ -72,7 +70,7 @@ def test_hello_fails(test_client):
@asyncio.coroutine
def test_hello_with_fake_loop(test_client):
with pytest.raises(AssertionError):
with pytest.raises(RuntimeError):
fake_loop = mock.Mock()
yield from test_client(web.Application(loop=fake_loop))
Expand Down Expand Up @@ -153,20 +151,16 @@ def make_app(loop):
yield from test_client(make_app)
""")
testdir.runpytest('-p', 'no:sugar')

# i dont know how to fix this
# result = testdir.runpytest('-p', 'no:sugar')
# result.assert_outcomes(passed=11, failed=1)
testdir.makeconftest(CONFTEST)
result = testdir.runpytest_subprocess('-p', 'no:sugar', '--loop=pyloop')
result.assert_outcomes(passed=11, failed=1)


@pytest.mark.skipif(sys.version_info < (3, 5), reason='old python')
def test_warning_checks(testdir, capsys):
testdir.makepyfile("""\
import asyncio
pytest_plugins = 'aiohttp.pytest_plugin'
async def foobar():
return 123
Expand All @@ -177,7 +171,8 @@ async def test_good():
async def test_bad():
foobar()
""")
result = testdir.runpytest('-p', 'no:sugar', '-s')
testdir.makeconftest(CONFTEST)
result = testdir.runpytest('-p', 'no:sugar', '-s', '--loop=pyloop')
result.assert_outcomes(passed=1, failed=1)
stdout, _ = capsys.readouterr()
assert ("test_warning_checks.py:__LINE__:coroutine 'foobar' was "
Expand All @@ -192,9 +187,6 @@ def test_aiohttp_plugin_async_fixture(testdir, capsys):
from aiohttp import web
pytest_plugins = 'aiohttp.pytest_plugin'
@asyncio.coroutine
def hello(request):
return web.Response(body=b'Hello, world')
Expand Down Expand Up @@ -244,9 +236,9 @@ def test_foo_without_loop(foo):
def test_bar(loop, bar):
assert bar is test_bar
""")
nb_loops = len(LOOP_FACTORIES)
result = testdir.runpytest('-p', 'no:sugar')
result.assert_outcomes(passed=3 * nb_loops, error=1)
testdir.makeconftest(CONFTEST)
result = testdir.runpytest_subprocess('-p', 'no:sugar', '--loop=pyloop')
result.assert_outcomes(passed=3, error=1)
result.stdout.fnmatch_lines(
"*Asynchronous fixtures must depend on the 'loop' fixture "
"or be used in tests depending from it."
Expand All @@ -263,8 +255,6 @@ def test_aiohttp_plugin_async_gen_fixture(testdir):
from aiohttp import web
pytest_plugins = 'aiohttp.pytest_plugin'
canary = mock.Mock()
Expand Down Expand Up @@ -292,6 +282,6 @@ async def test_hello(cli):
def test_finalized():
assert canary.called is True
""")
nb_loops = len(LOOP_FACTORIES)
result = testdir.runpytest('-p', 'no:sugar')
result.assert_outcomes(passed=1 * nb_loops + 1)
testdir.makeconftest(CONFTEST)
result = testdir.runpytest_subprocess('-p', 'no:sugar', '--loop=pyloop')
result.assert_outcomes(passed=2)

0 comments on commit 893f0c9

Please sign in to comment.