diff --git a/changelog/15051.bugfix.rst b/changelog/15051.bugfix.rst new file mode 100644 index 00000000000..a8ca38dbaa6 --- /dev/null +++ b/changelog/15051.bugfix.rst @@ -0,0 +1 @@ +Fixed crash when using :option:`--fixtures-per-test` on a fixture-using doctest. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 7656fca2f5b..68fcbb3970c 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -2455,10 +2455,6 @@ def _show_fixtures_per_test(config: Config, session: Session) -> None: tw = _pytest.config.create_terminal_writer(config) verbose = config.get_verbosity() - def get_best_relpath(func) -> str: - loc = getlocation(func, invocation_dir) - return bestrelpath(invocation_dir, Path(loc)) - def write_fixture(fixture_def: FixtureDef[object]) -> None: argname = fixture_def.argname if verbose <= 0 and argname.startswith("_"): @@ -2484,11 +2480,13 @@ def write_item(item: nodes.Item) -> None: # This test item does not use any fixtures. return + path, lineno, _test_name = item.reportinfo() + relpath = str(bestrelpath(invocation_dir, Path(path))) + title = f"{relpath}:{lineno + 1}" if lineno is not None else relpath + tw.line() tw.sep("-", f"fixtures used by {item.name}") - # TODO: Fix this type ignore. - tw.sep("-", f"({get_best_relpath(item.function)})") # type: ignore[attr-defined] - + tw.sep("-", f"({title})") for fixturedef in fixturedefs: write_fixture(fixturedef) diff --git a/testing/python/show_fixtures_per_test.py b/testing/python/show_fixtures_per_test.py index 2362847f338..f28d825bd28 100644 --- a/testing/python/show_fixtures_per_test.py +++ b/testing/python/show_fixtures_per_test.py @@ -161,27 +161,49 @@ def test_args(arg2, arg3): def test_doctest_items(pytester: Pytester) -> None: + pytester.makeconftest( + """ + import pytest + + @pytest.fixture(autouse=True) + def one(): + return 1 + """ + ) pytester.makepyfile( ''' def foo(): """ - >>> 1 + 1 + >>> getfixture('one') + 1 2 """ ''' ) pytester.maketxtfile( """ - >>> 1 + 1 + >>> getfixture('one') + 1 2 """ ) + result = pytester.runpytest( "--fixtures-per-test", "--doctest-modules", "--doctest-glob=*.txt", "-v" ) - assert result.ret == 0 - result.stdout.fnmatch_lines(["*collected 2 items*"]) + assert result.ret == 0 + result.stdout.fnmatch_lines( + [ + "*collected 2 items*", + "* fixtures used by test_doctest_items.foo *", + "* (test_doctest_items.py:2) *", + "one -- conftest.py:3", + "* no docstring available", + "* fixtures used by test_doctest_items.txt *", + "* (test_doctest_items.txt:1) *", + "one -- conftest.py:3", + "* no docstring available", + ] + ) def test_multiline_docstring_in_module(pytester: Pytester) -> None: