diff --git a/changelog.d/1584.fixed.rst b/changelog.d/1584.fixed.rst new file mode 100644 index 00000000..1e146fc3 --- /dev/null +++ b/changelog.d/1584.fixed.rst @@ -0,0 +1 @@ +Fixed an invalid ``loop_scope`` in the ``asyncio`` marker being reported as a bare ``AssertionError`` exposing a Python set repr, instead of a usage error that names the argument and lists the valid scopes. diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 38b75e41..e99a8d03 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -979,8 +979,7 @@ def _parse_asyncio_marker( scope = asyncio_marker.kwargs.get("loop_scope") or asyncio_marker.kwargs.get( "scope" ) - if scope is not None: - assert scope in {"function", "class", "module", "package", "session"} + _validate_scope(scope, "loop_scope") marker_value = asyncio_marker.kwargs.get("loop_factories") if marker_value is None: return scope, None diff --git a/tests/test_fixture_loop_scopes.py b/tests/test_fixture_loop_scopes.py index a25e56a0..a051b8a1 100644 --- a/tests/test_fixture_loop_scopes.py +++ b/tests/test_fixture_loop_scopes.py @@ -126,3 +126,23 @@ def test_invalid_default_fixture_loop_scope_raises_error(pytester: Pytester): "function, class, module, package, session." ] ) + + +def test_invalid_marker_loop_scope_raises_error(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile("""\ + import pytest + + @pytest.mark.asyncio(loop_scope="invalid_scope") + async def test_invalid_loop_scope(): + pass + """) + result = pytester.runpytest("--assert=plain") + # The exception class is rendered as pytest.UsageError on newer pytest and as + # _pytest.config.exceptions.UsageError on the oldest supported version. + result.stdout.fnmatch_lines( + [ + "*UsageError: 'invalid_scope' is not a valid loop_scope. " + "Valid scopes are: function, class, module, package, session." + ] + )