Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support coroutines with async and await syntax #17

Merged
merged 2 commits into from
Dec 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
language: python
python: 3.3
python: 3.5

env:
- TOX_ENV=py33
- TOX_ENV=py34
- TOX_ENV=py35

install:
- pip install tox
Expand Down
7 changes: 6 additions & 1 deletion pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
import pytest


def _is_coroutine(obj):
"""Check to see if an object is really an asyncio coroutine."""
return asyncio.iscoroutinefunction(obj) or inspect.isgeneratorfunction(obj)


def pytest_configure(config):
config.addinivalue_line("markers",
"asyncio: "
Expand All @@ -20,7 +25,7 @@ def pytest_configure(config):

@pytest.mark.tryfirst
def pytest_pycollect_makeitem(collector, name, obj):
if collector.funcnamefilter(name) and inspect.isgeneratorfunction(obj):
if collector.funcnamefilter(name) and _is_coroutine(obj):
item = pytest.Function(name, parent=collector)
if ('asyncio' in item.keywords or
'asyncio_process_pool' in item.keywords):
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def find_version(*file_paths):
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Topic :: Software Development :: Testing",
],
install_requires=[
Expand Down
99 changes: 99 additions & 0 deletions tests/test_simple_35.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""Quick'n'dirty unit tests using async and await syntax."""

import asyncio
import sys

import pytest

pytestmark = pytest.mark.skipif(
sys.version_info[:2] < (3, 5),
reason='This syntax is only valid in 3.5 and newer')


@asyncio.coroutine
def async_coro(loop):
yield from asyncio.sleep(0, loop=loop)
return 'ok'


# PEP 492 added the syntax for these tests to Python 3.5. Older versions
# can't even parse the module to let skipif exclude the tests. To get
# around this, all tests are defined in a string which can be compiled
# and executed on appropriate versions of Python.
_possible_tests = '''
@pytest.mark.asyncio
async def test_asyncio_marker():
"""Test the asyncio pytest marker."""


@pytest.mark.asyncio
async def test_asyncio_marker_with_default_param(a_param=None):
"""Test the asyncio pytest marker."""


@pytest.mark.asyncio_process_pool
async def test_asyncio_process_pool_marker(event_loop):
ret = await async_coro(event_loop)
assert ret == 'ok'


@pytest.mark.asyncio
async def test_unused_port_fixture(unused_tcp_port, event_loop):
"""Test the unused TCP port fixture."""
async def closer(_, writer):
writer.close()

server1 = await asyncio.start_server(closer, host='localhost',
port=unused_tcp_port,
loop=event_loop)

server1.close()
await server1.wait_closed()


@pytest.mark.asyncio
async def test_unused_port_factory_fixture(unused_tcp_port_factory, event_loop):
"""Test the unused TCP port factory fixture."""

async def closer(_, writer):
writer.close()

port1, port2, port3 = (unused_tcp_port_factory(), unused_tcp_port_factory(),
unused_tcp_port_factory())

server1 = await asyncio.start_server(closer, host='localhost',
port=port1,
loop=event_loop)
server2 = await asyncio.start_server(closer, host='localhost',
port=port2,
loop=event_loop)
server3 = await asyncio.start_server(closer, host='localhost',
port=port3,
loop=event_loop)

for port in port1, port2, port3:
with pytest.raises(IOError):
await asyncio.start_server(closer, host='localhost',
port=port,
loop=event_loop)

server1.close()
await server1.wait_closed()
server2.close()
await server2.wait_closed()
server3.close()
await server3.wait_closed()


class Test:
"""Test that asyncio marked functions work in test methods."""

@pytest.mark.asyncio
async def test_asyncio_marker_method(self, event_loop):
"""Test the asyncio pytest marker in a Test class."""
ret = await async_coro(event_loop)
assert ret == 'ok'
'''

if sys.version_info[:2] >= (3, 5):
exec(compile(_possible_tests, __file__, 'exec'))
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py33, py34
envlist = py33, py34, py35

[testenv]
deps =
Expand Down