Skip to content

Fix internal error caused by pytest.skip statements #702

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

Merged
merged 2 commits into from
Dec 3, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/source/reference/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Changelog
=========

0.23.1 (2023-12-03)
===================
- Fixes a bug that caused an internal pytest error when using module-level skips `#701 <https://github.com/pytest-dev/pytest-asyncio/issues/701>`_


0.23.0 (2023-12-03)
===================
This release is backwards-compatible with v0.21.
Expand Down
11 changes: 10 additions & 1 deletion pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
)

import pytest
from _pytest.outcomes import OutcomeException
from pytest import (
Class,
Collector,
Expand Down Expand Up @@ -607,7 +608,15 @@ def scoped_event_loop(
# know it exists. We work around this by attaching the fixture function to the
# collected Python class, where it will be picked up by pytest.Class.collect()
# or pytest.Module.collect(), respectively
collector.obj.__pytest_asyncio_scoped_event_loop = scoped_event_loop
try:
collector.obj.__pytest_asyncio_scoped_event_loop = scoped_event_loop
except (OutcomeException, Collector.CollectError):
# Accessing Module.obj triggers a module import executing module-level
# statements. A module-level pytest.skip statement raises the "Skipped"
# OutcomeException or a Collector.CollectError, if the "allow_module_level"
# kwargs is missing. These cases are handled correctly when they happen inside
# Collector.collect(), but this hook runs before the actual collect call.
return
# When collector is a package, collector.obj is the package's __init__.py.
# pytest doesn't seem to collect fixtures in __init__.py.
# Using parsefactories to collect fixtures in __init__.py their baseid will end
Expand Down
90 changes: 90 additions & 0 deletions tests/test_pytest_skip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from textwrap import dedent

from pytest import Pytester


def test_asyncio_strict_mode_skip(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest

pytest_plugins = "pytest_asyncio"

@pytest.mark.asyncio
async def test_no_warning_on_skip():
pytest.skip("Test a skip error inside asyncio")
"""
)
)
result = pytester.runpytest("--asyncio-mode=strict")
result.assert_outcomes(skipped=1)


def test_asyncio_auto_mode_skip(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest

pytest_plugins = "pytest_asyncio"

async def test_no_warning_on_skip():
pytest.skip("Test a skip error inside asyncio")
"""
)
)
result = pytester.runpytest("--asyncio-mode=auto")
result.assert_outcomes(skipped=1)


def test_asyncio_strict_mode_module_level_skip(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest

pytest.skip("Skip all tests", allow_module_level=True)

@pytest.mark.asyncio
async def test_is_skipped():
pass
"""
)
)
result = pytester.runpytest("--asyncio-mode=strict")
result.assert_outcomes(skipped=1)


def test_asyncio_auto_mode_module_level_skip(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest

pytest.skip("Skip all tests", allow_module_level=True)

async def test_is_skipped():
pass
"""
)
)
result = pytester.runpytest("--asyncio-mode=auto")
result.assert_outcomes(skipped=1)


def test_asyncio_auto_mode_wrong_skip_usage(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest

pytest.skip("Skip all tests")

async def test_is_skipped():
pass
"""
)
)
result = pytester.runpytest("--asyncio-mode=auto")
result.assert_outcomes(errors=1)
35 changes: 0 additions & 35 deletions tests/test_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,41 +100,6 @@ async def test_event_loop_before_fixture(self, loop):
assert await loop.run_in_executor(None, self.foo) == 1


def test_asyncio_marker_compatibility_with_skip(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest

pytest_plugins = "pytest_asyncio"

@pytest.mark.asyncio
async def test_no_warning_on_skip():
pytest.skip("Test a skip error inside asyncio")
"""
)
)
result = pytester.runpytest("--asyncio-mode=strict")
result.assert_outcomes(skipped=1)


def test_asyncio_auto_mode_compatibility_with_skip(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest

pytest_plugins = "pytest_asyncio"

async def test_no_warning_on_skip():
pytest.skip("Test a skip error inside asyncio")
"""
)
)
result = pytester.runpytest("--asyncio-mode=auto")
result.assert_outcomes(skipped=1)


def test_invalid_asyncio_mode(testdir):
result = testdir.runpytest("-o", "asyncio_mode=True")
result.stderr.no_fnmatch_line("INTERNALERROR> *")
Expand Down