Skip to content

Commit b208df6

Browse files
jakkdlseifertm
authored andcommitted
feat: Warn if asyncio test requests async pytest fixture in strict mode
fix test make it raise PytestDeprecationWarning instead add changelog entry docs: Changed release date of v0.25.0 to UNRELEASED.
1 parent 1057723 commit b208df6

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

docs/reference/changelog.rst

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
Changelog
33
=========
44

5+
0.25.0 (UNRELEASED)
6+
===================
7+
- Deprecated: Added warning when asyncio test requests async ``@pytest.fixture`` in strict mode. This will become an error in a future version of flake8-asyncio. `#979 <https://github.com/pytest-dev/pytest-asyncio/pull/979>`_
8+
59
0.24.0 (2024-08-22)
610
===================
711
- BREAKING: Updated minimum supported pytest version to v8.2.0

pytest_asyncio/plugin.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,32 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> object | None:
880880
"""
881881
if pyfuncitem.get_closest_marker("asyncio") is not None:
882882
if isinstance(pyfuncitem, PytestAsyncioFunction):
883-
pass
883+
asyncio_mode = _get_asyncio_mode(pyfuncitem.config)
884+
for fixname, fixtures in pyfuncitem._fixtureinfo.name2fixturedefs.items():
885+
# name2fixturedefs is a dict between fixture name and a list of matching
886+
# fixturedefs. The last entry in the list is closest and the one used.
887+
func = fixtures[-1].func
888+
if (
889+
_is_coroutine_or_asyncgen(func)
890+
and not _is_asyncio_fixture_function(func)
891+
and asyncio_mode == Mode.STRICT
892+
):
893+
warnings.warn(
894+
PytestDeprecationWarning(
895+
f"asyncio test {pyfuncitem.name!r} requested async "
896+
"@pytest.fixture "
897+
f"{fixname!r} in strict mode. "
898+
"You might want to use @pytest_asyncio.fixture or switch "
899+
"to auto mode. "
900+
"This will become an error in future versions of "
901+
"flake8-asyncio."
902+
),
903+
stacklevel=1,
904+
)
905+
# no stacklevel points at the users code, so we set stacklevel=1
906+
# so it at least indicates that it's the plugin complaining.
907+
# Pytest gives the test file & name in the warnings summary at least
908+
884909
else:
885910
pyfuncitem.warn(
886911
pytest.PytestWarning(

tests/modes/test_strict_mode.py

+87
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,90 @@ async def test_anything(any_fixture):
124124
"*coroutine 'any_fixture' was never awaited*",
125125
],
126126
)
127+
128+
129+
def test_strict_mode_marked_test_unmarked_fixture_warning(pytester: Pytester):
130+
pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function")
131+
pytester.makepyfile(
132+
dedent(
133+
"""\
134+
import pytest
135+
136+
# Not using pytest_asyncio.fixture
137+
@pytest.fixture()
138+
async def any_fixture():
139+
pass
140+
141+
@pytest.mark.asyncio
142+
async def test_anything(any_fixture):
143+
# suppress unawaited coroutine warning
144+
try:
145+
any_fixture.send(None)
146+
except StopIteration:
147+
pass
148+
"""
149+
)
150+
)
151+
result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W default")
152+
result.assert_outcomes(passed=1, failed=0, skipped=0, warnings=1)
153+
result.stdout.fnmatch_lines(
154+
[
155+
"*warnings summary*",
156+
(
157+
"test_strict_mode_marked_test_unmarked_fixture_warning.py::"
158+
"test_anything"
159+
),
160+
(
161+
"*/pytest_asyncio/plugin.py:*: PytestDeprecationWarning: "
162+
"asyncio test 'test_anything' requested async "
163+
"@pytest.fixture 'any_fixture' in strict mode. "
164+
"You might want to use @pytest_asyncio.fixture or switch to "
165+
"auto mode. "
166+
"This will become an error in future versions of flake8-asyncio."
167+
),
168+
],
169+
)
170+
171+
172+
# autouse is not handled in any special way currently
173+
def test_strict_mode_marked_test_unmarked_autouse_fixture_warning(pytester: Pytester):
174+
pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function")
175+
pytester.makepyfile(
176+
dedent(
177+
"""\
178+
import pytest
179+
180+
# Not using pytest_asyncio.fixture
181+
@pytest.fixture(autouse=True)
182+
async def any_fixture():
183+
pass
184+
185+
@pytest.mark.asyncio
186+
async def test_anything(any_fixture):
187+
# suppress unawaited coroutine warning
188+
try:
189+
any_fixture.send(None)
190+
except StopIteration:
191+
pass
192+
"""
193+
)
194+
)
195+
result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W default")
196+
result.assert_outcomes(passed=1, warnings=1)
197+
result.stdout.fnmatch_lines(
198+
[
199+
"*warnings summary*",
200+
(
201+
"test_strict_mode_marked_test_unmarked_autouse_fixture_warning.py::"
202+
"test_anything"
203+
),
204+
(
205+
"*/pytest_asyncio/plugin.py:*: PytestDeprecationWarning: "
206+
"*asyncio test 'test_anything' requested async "
207+
"@pytest.fixture 'any_fixture' in strict mode. "
208+
"You might want to use @pytest_asyncio.fixture or switch to "
209+
"auto mode. "
210+
"This will become an error in future versions of flake8-asyncio."
211+
),
212+
],
213+
)

0 commit comments

Comments
 (0)