Skip to content

add feature to view fixture source location in invocations with --fixtures-per-test option #8626

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 8 commits into from
May 14, 2021
5 changes: 5 additions & 0 deletions changelog/8606.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pytest invocations with ``--fixtures-per-test`` and ``--fixtures`` have been enabled with:

- Fixture location path printed with the fixture name.
- First section of the fixture's docstring printed under the fixture name.
- Whole of fixture's docstring printed under the fixture name using ``--verbose`` option.
23 changes: 11 additions & 12 deletions src/_pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -1428,15 +1428,15 @@ def write_fixture(fixture_def: fixtures.FixtureDef[object]) -> None:
argname = fixture_def.argname
if verbose <= 0 and argname.startswith("_"):
return
if verbose > 0:
bestrel = get_best_relpath(fixture_def.func)
funcargspec = f"{argname} -- {bestrel}"
else:
funcargspec = argname
tw.line(funcargspec, green=True)
bestrel = get_best_relpath(fixture_def.func)
tw.write(f"{argname}", green=True)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@The-Compiler, I noticed your suggestion to use argname in this line as a direct variable reference instead of using it as a formatted string. I am not able to find that comment to reference it.

I think that would be a good thing to do and keeps things consistent. Please let me know if this small change can go in as a separate PR.

tw.write(f" -- {bestrel}", yellow=True)
tw.write("\n")
fixture_doc = inspect.getdoc(fixture_def.func)
if fixture_doc:
write_docstring(tw, fixture_doc)
write_docstring(
tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc
)
else:
tw.line(" no docstring available", red=True)

Expand Down Expand Up @@ -1508,18 +1508,17 @@ def _showfixtures_main(config: Config, session: Session) -> None:
tw.line()
tw.sep("-", f"fixtures defined from {module}")
currentmodule = module
if verbose <= 0 and argname[0] == "_":
if verbose <= 0 and argname.startswith("_"):
continue
tw.write(argname, green=True)
tw.write(f"{argname}", green=True)
if fixturedef.scope != "function":
tw.write(" [%s scope]" % fixturedef.scope, cyan=True)
if verbose > 0:
tw.write(" -- %s" % bestrel, yellow=True)
tw.write(f" -- {bestrel}", yellow=True)
tw.write("\n")
loc = getlocation(fixturedef.func, str(curdir))
doc = inspect.getdoc(fixturedef.func)
if doc:
write_docstring(tw, doc)
write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc)
else:
tw.line(f" {loc}: no docstring available", red=True)
tw.line()
Expand Down
26 changes: 13 additions & 13 deletions testing/python/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -3334,9 +3334,9 @@ def test_show_fixtures(self, pytester: Pytester) -> None:
result = pytester.runpytest("--fixtures")
result.stdout.fnmatch_lines(
[
"tmp_path_factory [[]session scope[]]",
"tmp_path_factory [[]session scope[]] -- *tmpdir.py*",
"*for the test session*",
"tmp_path",
"tmp_path -- *",
"*temporary directory*",
]
)
Expand Down Expand Up @@ -3367,9 +3367,9 @@ def arg1():
result = pytester.runpytest("--fixtures", p)
result.stdout.fnmatch_lines(
"""
*tmp_path
*tmp_path -- *
*fixtures defined from*
*arg1*
*arg1 -- test_show_fixtures_testmodule.py:6*
*hello world*
"""
)
Expand Down Expand Up @@ -3429,10 +3429,10 @@ def arg2():
textwrap.dedent(
"""\
* fixtures defined from test_show_fixtures_trimmed_doc *
arg2
arg2 -- test_show_fixtures_trimmed_doc.py:10
line1
line2
arg1
arg1 -- test_show_fixtures_trimmed_doc.py:3
line1
line2
"""
Expand All @@ -3458,7 +3458,7 @@ def fixture1():
textwrap.dedent(
"""\
* fixtures defined from test_show_fixtures_indented_doc *
fixture1
fixture1 -- test_show_fixtures_indented_doc.py:3
line1
indented line
"""
Expand Down Expand Up @@ -3486,7 +3486,7 @@ def fixture1():
textwrap.dedent(
"""\
* fixtures defined from test_show_fixtures_indented_doc_first_line_unindented *
fixture1
fixture1 -- test_show_fixtures_indented_doc_first_line_unindented.py:3
line1
line2
indented line
Expand Down Expand Up @@ -3514,7 +3514,7 @@ def fixture1(self):
textwrap.dedent(
"""\
* fixtures defined from test_show_fixtures_indented_in_class *
fixture1
fixture1 -- test_show_fixtures_indented_in_class.py:4
line1
line2
indented line
Expand Down Expand Up @@ -3554,11 +3554,11 @@ def test_b(fix_b):
result.stdout.fnmatch_lines(
"""
* fixtures defined from test_a *
fix_a
fix_a -- test_a.py:4
Fixture A

* fixtures defined from test_b *
fix_b
fix_b -- test_b.py:4
Fixture B
"""
)
Expand Down Expand Up @@ -3594,11 +3594,11 @@ def test_bar(arg1):
result.stdout.fnmatch_lines(
"""
* fixtures defined from conftest *
arg1
arg1 -- conftest.py:3
Hello World in conftest.py

* fixtures defined from test_show_fixtures_with_same_name *
arg1
arg1 -- test_show_fixtures_with_same_name.py:3
Hi from test module
"""
)
Expand Down
87 changes: 79 additions & 8 deletions testing/python/show_fixtures_per_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def test_arg1(arg1):
[
"*fixtures used by test_arg1*",
"*(test_fixtures_in_module.py:9)*",
"arg1",
"arg1 -- test_fixtures_in_module.py:6",
" arg1 docstring",
]
)
Expand Down Expand Up @@ -68,17 +68,16 @@ def test_arg3(arg3):
[
"*fixtures used by test_arg2*",
"*(test_fixtures_in_conftest.py:2)*",
"arg2",
"arg2 -- conftest.py:6",
" arg2 docstring",
"*fixtures used by test_arg3*",
"*(test_fixtures_in_conftest.py:4)*",
"arg1",
"arg1 -- conftest.py:3",
" arg1 docstring",
"arg2",
"arg2 -- conftest.py:6",
" arg2 docstring",
"arg3",
"arg3 -- conftest.py:9",
" arg3",
" docstring",
]
)

Expand Down Expand Up @@ -112,9 +111,9 @@ def test_args(arg1, arg2):
[
"*fixtures used by test_args*",
"*(test_should_show_fixtures_used_by_test.py:6)*",
"arg1",
"arg1 -- test_should_show_fixtures_used_by_test.py:3",
" arg1 from testmodule",
"arg2",
"arg2 -- conftest.py:6",
" arg2 from conftest",
]
)
Expand Down Expand Up @@ -181,3 +180,75 @@ def foo():
assert result.ret == 0

result.stdout.fnmatch_lines(["*collected 2 items*"])


def test_multiline_docstring_in_module(pytester: Pytester) -> None:
p = pytester.makepyfile(
'''
import pytest
@pytest.fixture
def arg1():
"""Docstring content that spans across multiple lines,
through second line,
and through third line.

Docstring content that extends into a second paragraph.

Docstring content that extends into a third paragraph.
"""
def test_arg1(arg1):
pass
'''
)

result = pytester.runpytest("--fixtures-per-test", p)
assert result.ret == 0

result.stdout.fnmatch_lines(
[
"*fixtures used by test_arg1*",
"*(test_multiline_docstring_in_module.py:13)*",
"arg1 -- test_multiline_docstring_in_module.py:3",
" Docstring content that spans across multiple lines,",
" through second line,",
" and through third line.",
]
)


def test_verbose_include_multiline_docstring(pytester: Pytester) -> None:
p = pytester.makepyfile(
'''
import pytest
@pytest.fixture
def arg1():
"""Docstring content that spans across multiple lines,
through second line,
and through third line.

Docstring content that extends into a second paragraph.

Docstring content that extends into a third paragraph.
"""
def test_arg1(arg1):
pass
'''
)

result = pytester.runpytest("--fixtures-per-test", "-v", p)
assert result.ret == 0

result.stdout.fnmatch_lines(
[
"*fixtures used by test_arg1*",
"*(test_verbose_include_multiline_docstring.py:13)*",
"arg1 -- test_verbose_include_multiline_docstring.py:3",
" Docstring content that spans across multiple lines,",
" through second line,",
" and through third line.",
" ",
" Docstring content that extends into a second paragraph.",
" ",
" Docstring content that extends into a third paragraph.",
]
)