Reputation: 29159
@pytest.fixture
def d_service():
c = DService()
return c
# @pytest.mark.asyncio # tried it too
async def test_get_file_list(d_service):
files = await d_service.get_file_list('')
print(files)
However, it got the following error?
collected 0 items / 1 errors =================================== ERRORS ==================================== ________________ ERROR collecting tests/e2e_tests/test_d.py _________________ ..\..\..\..\..\anaconda3\lib\site-packages\pluggy\__init__.py:617: in __call__ return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) ..\..\..\..\..\anaconda3\lib\site-packages\pluggy\__init__.py:222: in _hookexec return self._inner_hookexec(hook, methods, kwargs) ..\..\..\..\..\anaconda3\lib\site-packages\pluggy\__init__.py:216: in firstresult=hook.spec_opts.get('firstresult'), ..\..\..\..\..\anaconda3\lib\site-packages\_pytest\python.py:171: in pytest_pycollect_makeitem res = outcome.get_result() ..\..\..\..\..\anaconda3\lib\site-packages\anyio\pytest_plugin.py:98: in pytest_pycollect_makeitem marker = collector.get_closest_marker('anyio') E AttributeError: 'Module' object has no attribute 'get_closest_marker' !!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!! =========================== 1 error in 2.53 seconds ===========================
I installed the following package. The error is gone but the test is skipped.
pip install pytest-asyncio
(base) PS>pytest -s tests\e2e_tests\test_d.py ================================================================================================================== test session starts =================================================================================================================== platform win32 -- Python 3.6.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: C:\Users\X01324908\source\rds\research_data_science\sftp\file_handler plugins: anyio-3.3.4, asyncio-0.16.0 collected 1 item tests\e2e_tests\test_d.py s ==================================================================================================================== warnings summary ==================================================================================================================== tests/e2e_tests/test_d.py::test_get_file_list c:\users\x01324908\anaconda3\lib\site-packages\_pytest\python.py:172: PytestUnhandledCoroutineWarning: async def functions are not natively supported and have been skipped. You need to install a suitable plugin for your async framework, for example: - anyio - pytest-asyncio - pytest-tornasync - pytest-trio - pytest-twisted warnings.warn(PytestUnhandledCoroutineWarning(msg.format(nodeid))) -- Docs: https://docs.pytest.org/en/stable/warnings.html =============
Upvotes: 49
Views: 62739
Reputation: 385
A decorator that runs the test coroutine in the event loop:
import asyncio
import inspect
def asyncio_run(async_func):
def wrapper(*args, **kwargs):
return asyncio.run(async_func(*args, **kwargs))
wrapper.__signature__ = inspect.signature(async_func) # without this, fixtures are not injected
return wrapper
@asyncio_run
async def test_get_file_list(d_service):
files = await d_service.get_file_list('')
print(files)
Avoid async tests as much as possible. Try to make most of your code pure — then most of your tests will be fast and reliable/deterministic (which might not be the case with asynchronous code). Search for "functional core, imperative shell" for more.
EDIT: You can ignore "functional core, imperative shell" in relation to tests, although that is still useful advice for design in general IMO. For tests you just have to abstract the effect type. Oh is this Python? Just use a better language, like Haskell or Scala.
Upvotes: 2
Reputation: 1435
You can make pytest-asyncio
automatically detect async def test_*
functions as proper test by adding a file in your tests/
folder called pytest.ini
with the following content:
# pytest.ini
[pytest]
asyncio_mode=auto
This way you don't even need to decorate/mark your async def
tests, as explained in the Modes section of the documentation.
Upvotes: 56
Reputation: 17237
This works for me, please try:
import asyncio
import pytest
pytest_plugins = ('pytest_asyncio',)
@pytest.mark.asyncio
async def test_simple():
await asyncio.sleep(0.5)
Output of pytest -v
confirms it passes:
collected 1 item
test_async.py::test_simple PASSED
And I have installed:
pytest 6.2.5
pytest-asyncio 0.16.0
# anyio not installed
Upvotes: 62