Description
Interesting things seem to happen with the current logic in 0.23.0a
when collecting async fixtures.
Running a venv with almost nothing installed:
# requirements.txt
pytest
pytest-asyncio==0.23.0a0
# pyproject.toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
A single dir tests
contains an __init__.py
and the test_async_fixtures.py
file; pytest is invoked as pytest tests/
This fails:
# tests/test_async_fixture.py
import asyncio
import pytest
@pytest.fixture(scope="package")
def event_loop_policy() -> asyncio.AbstractEventLoopPolicy:
return asyncio.DefaultEventLoopPolicy()
@pytest.fixture(scope="package")
async def async_fixture():
yield 7
async def test_async_fixture(async_fixture):
assert async_fixture == 7
Complaining:
ScopeMismatch: You tried to access the function scoped fixture event_loop with a package scoped request object, involved factories:
tests/test_fixture.py:13: def async_fixture()
Hmm. As a guess, is async_fixture
implicitly requesting the wrong event loop? What happens if I mark it?
@pytest.fixture(scope="package")
@pytest.mark.asyncio(scope="package")
async def async_fixture():
yield 7
No, the same as before (I have no idea if one is supposed to be able to mark fixtures like this).
What about marking the whole module explicitly?
import asyncio
import pytest
pytestmark = pytest.mark.asyncio(scope="package")
...
Ah! now we get a more interesting error:
file /tmp/t/tests/test_fixture.py, line 20
async def test_async_fixture(async_fixture):
assert async_fixture == 7
E fixture 'tests/__init__.py::<event_loop>' not found
> available fixtures: _session_event_loop, async_fixture, cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, event_loop, event_loop_policy, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tests/test_fixture.py::<event_loop>, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory, unused_tcp_port, unused_tcp_port_factory, unused_udp_port, unused_udp_port_factory
> use 'pytest --fixtures [testpath]' for help on them.
What about marking the test function with an explicit scope?
@pytest.mark.asyncio(scope="package")
async def test_async_fixture(async_fixture):
assert async_fixture == 7
This raises the new 'Multiple asyncio event loops with different scopes' error.
Traceback
.venv/lib/python3.11/site-packages/_pytest/runner.py:341: in from_call
result: Optional[TResult] = func()
.venv/lib/python3.11/site-packages/_pytest/runner.py:372: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
.venv/lib/python3.11/site-packages/_pytest/python.py:534: in collect
return super().collect()
.venv/lib/python3.11/site-packages/_pytest/python.py:455: in collect
res = ihook.pytest_pycollect_makeitem(
.venv/lib/python3.11/site-packages/pluggy/_hooks.py:493: in __call__
return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
.venv/lib/python3.11/site-packages/pluggy/_manager.py:115: in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
.venv/lib/python3.11/site-packages/pytest_asyncio/plugin.py:525: in pytest_pycollect_makeitem_convert_async_functions_to_subclass
node_or_list_of_nodes = hook_result.get_result()
.venv/lib/python3.11/site-packages/_pytest/python.py:271: in pytest_pycollect_makeitem
return list(collector._genfunctions(name, obj))
.venv/lib/python3.11/site-packages/_pytest/python.py:498: in _genfunctions
self.ihook.pytest_generate_tests.call_extra(methods, dict(metafunc=metafunc))
.venv/lib/python3.11/site-packages/pluggy/_hooks.py:552: in call_extra
return self._hookexec(self.name, hookimpls, kwargs, firstresult)
.venv/lib/python3.11/site-packages/pluggy/_manager.py:115: in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
.venv/lib/python3.11/site-packages/pytest_asyncio/plugin.py:674: in pytest_generate_tests
raise MultipleEventLoopsRequestedError(
E pytest_asyncio.plugin.MultipleEventLoopsRequestedError: Multiple asyncio event loops with different scopes have been requested
E by tests/test_fixture.py::test_async_fixture. The test explicitly requests the event_loop fixture, while
E another event loop with package scope is provided by tests/__init__.py.
E Remove "event_loop" from the requested fixture in your test to run the test
E in a package-scoped event loop or remove the scope argument from the "asyncio"
E mark to run the test in a function-scoped event loop.
Assuming I'm using the new code correctly, it looks like there's a problem with async fixtures and policies. At any rate here's a failing test case.