Skip to content

Commit c516dba

Browse files
add feature to view fixture source location in invocations with --fixtures-per-test option (#8626)
* add feature to view fixture source location in invocations with --fixtures-per-test option * remove unrelated changes to show_fixtures_per_test::test_doctest_items * eshew the extraneous else in _show_fixtures_per_test.write_fixture * enable the accommodation of multi-line docstring with --fixtures-per-test option * add feature to view fixture source location in invocations with --fixtures * add colour encoding to fixture location paths * add changelog for #8606 fixing * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 33c6ad5 commit c516dba

File tree

4 files changed

+108
-33
lines changed

4 files changed

+108
-33
lines changed

changelog/8606.feature.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pytest invocations with ``--fixtures-per-test`` and ``--fixtures`` have been enabled with:
2+
3+
- Fixture location path printed with the fixture name.
4+
- First section of the fixture's docstring printed under the fixture name.
5+
- Whole of fixture's docstring printed under the fixture name using ``--verbose`` option.

src/_pytest/python.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,15 +1428,15 @@ def write_fixture(fixture_def: fixtures.FixtureDef[object]) -> None:
14281428
argname = fixture_def.argname
14291429
if verbose <= 0 and argname.startswith("_"):
14301430
return
1431-
if verbose > 0:
1432-
bestrel = get_best_relpath(fixture_def.func)
1433-
funcargspec = f"{argname} -- {bestrel}"
1434-
else:
1435-
funcargspec = argname
1436-
tw.line(funcargspec, green=True)
1431+
bestrel = get_best_relpath(fixture_def.func)
1432+
tw.write(f"{argname}", green=True)
1433+
tw.write(f" -- {bestrel}", yellow=True)
1434+
tw.write("\n")
14371435
fixture_doc = inspect.getdoc(fixture_def.func)
14381436
if fixture_doc:
1439-
write_docstring(tw, fixture_doc)
1437+
write_docstring(
1438+
tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc
1439+
)
14401440
else:
14411441
tw.line(" no docstring available", red=True)
14421442

@@ -1508,18 +1508,17 @@ def _showfixtures_main(config: Config, session: Session) -> None:
15081508
tw.line()
15091509
tw.sep("-", f"fixtures defined from {module}")
15101510
currentmodule = module
1511-
if verbose <= 0 and argname[0] == "_":
1511+
if verbose <= 0 and argname.startswith("_"):
15121512
continue
1513-
tw.write(argname, green=True)
1513+
tw.write(f"{argname}", green=True)
15141514
if fixturedef.scope != "function":
15151515
tw.write(" [%s scope]" % fixturedef.scope, cyan=True)
1516-
if verbose > 0:
1517-
tw.write(" -- %s" % bestrel, yellow=True)
1516+
tw.write(f" -- {bestrel}", yellow=True)
15181517
tw.write("\n")
15191518
loc = getlocation(fixturedef.func, str(curdir))
15201519
doc = inspect.getdoc(fixturedef.func)
15211520
if doc:
1522-
write_docstring(tw, doc)
1521+
write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc)
15231522
else:
15241523
tw.line(f" {loc}: no docstring available", red=True)
15251524
tw.line()

testing/python/fixtures.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3334,9 +3334,9 @@ def test_show_fixtures(self, pytester: Pytester) -> None:
33343334
result = pytester.runpytest("--fixtures")
33353335
result.stdout.fnmatch_lines(
33363336
[
3337-
"tmp_path_factory [[]session scope[]]",
3337+
"tmp_path_factory [[]session scope[]] -- *tmpdir.py*",
33383338
"*for the test session*",
3339-
"tmp_path",
3339+
"tmp_path -- *",
33403340
"*temporary directory*",
33413341
]
33423342
)
@@ -3367,9 +3367,9 @@ def arg1():
33673367
result = pytester.runpytest("--fixtures", p)
33683368
result.stdout.fnmatch_lines(
33693369
"""
3370-
*tmp_path
3370+
*tmp_path -- *
33713371
*fixtures defined from*
3372-
*arg1*
3372+
*arg1 -- test_show_fixtures_testmodule.py:6*
33733373
*hello world*
33743374
"""
33753375
)
@@ -3429,10 +3429,10 @@ def arg2():
34293429
textwrap.dedent(
34303430
"""\
34313431
* fixtures defined from test_show_fixtures_trimmed_doc *
3432-
arg2
3432+
arg2 -- test_show_fixtures_trimmed_doc.py:10
34333433
line1
34343434
line2
3435-
arg1
3435+
arg1 -- test_show_fixtures_trimmed_doc.py:3
34363436
line1
34373437
line2
34383438
"""
@@ -3458,7 +3458,7 @@ def fixture1():
34583458
textwrap.dedent(
34593459
"""\
34603460
* fixtures defined from test_show_fixtures_indented_doc *
3461-
fixture1
3461+
fixture1 -- test_show_fixtures_indented_doc.py:3
34623462
line1
34633463
indented line
34643464
"""
@@ -3486,7 +3486,7 @@ def fixture1():
34863486
textwrap.dedent(
34873487
"""\
34883488
* fixtures defined from test_show_fixtures_indented_doc_first_line_unindented *
3489-
fixture1
3489+
fixture1 -- test_show_fixtures_indented_doc_first_line_unindented.py:3
34903490
line1
34913491
line2
34923492
indented line
@@ -3514,7 +3514,7 @@ def fixture1(self):
35143514
textwrap.dedent(
35153515
"""\
35163516
* fixtures defined from test_show_fixtures_indented_in_class *
3517-
fixture1
3517+
fixture1 -- test_show_fixtures_indented_in_class.py:4
35183518
line1
35193519
line2
35203520
indented line
@@ -3554,11 +3554,11 @@ def test_b(fix_b):
35543554
result.stdout.fnmatch_lines(
35553555
"""
35563556
* fixtures defined from test_a *
3557-
fix_a
3557+
fix_a -- test_a.py:4
35583558
Fixture A
35593559
35603560
* fixtures defined from test_b *
3561-
fix_b
3561+
fix_b -- test_b.py:4
35623562
Fixture B
35633563
"""
35643564
)
@@ -3594,11 +3594,11 @@ def test_bar(arg1):
35943594
result.stdout.fnmatch_lines(
35953595
"""
35963596
* fixtures defined from conftest *
3597-
arg1
3597+
arg1 -- conftest.py:3
35983598
Hello World in conftest.py
35993599
36003600
* fixtures defined from test_show_fixtures_with_same_name *
3601-
arg1
3601+
arg1 -- test_show_fixtures_with_same_name.py:3
36023602
Hi from test module
36033603
"""
36043604
)

testing/python/show_fixtures_per_test.py

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_arg1(arg1):
2929
[
3030
"*fixtures used by test_arg1*",
3131
"*(test_fixtures_in_module.py:9)*",
32-
"arg1",
32+
"arg1 -- test_fixtures_in_module.py:6",
3333
" arg1 docstring",
3434
]
3535
)
@@ -68,17 +68,16 @@ def test_arg3(arg3):
6868
[
6969
"*fixtures used by test_arg2*",
7070
"*(test_fixtures_in_conftest.py:2)*",
71-
"arg2",
71+
"arg2 -- conftest.py:6",
7272
" arg2 docstring",
7373
"*fixtures used by test_arg3*",
7474
"*(test_fixtures_in_conftest.py:4)*",
75-
"arg1",
75+
"arg1 -- conftest.py:3",
7676
" arg1 docstring",
77-
"arg2",
77+
"arg2 -- conftest.py:6",
7878
" arg2 docstring",
79-
"arg3",
79+
"arg3 -- conftest.py:9",
8080
" arg3",
81-
" docstring",
8281
]
8382
)
8483

@@ -112,9 +111,9 @@ def test_args(arg1, arg2):
112111
[
113112
"*fixtures used by test_args*",
114113
"*(test_should_show_fixtures_used_by_test.py:6)*",
115-
"arg1",
114+
"arg1 -- test_should_show_fixtures_used_by_test.py:3",
116115
" arg1 from testmodule",
117-
"arg2",
116+
"arg2 -- conftest.py:6",
118117
" arg2 from conftest",
119118
]
120119
)
@@ -181,3 +180,75 @@ def foo():
181180
assert result.ret == 0
182181

183182
result.stdout.fnmatch_lines(["*collected 2 items*"])
183+
184+
185+
def test_multiline_docstring_in_module(pytester: Pytester) -> None:
186+
p = pytester.makepyfile(
187+
'''
188+
import pytest
189+
@pytest.fixture
190+
def arg1():
191+
"""Docstring content that spans across multiple lines,
192+
through second line,
193+
and through third line.
194+
195+
Docstring content that extends into a second paragraph.
196+
197+
Docstring content that extends into a third paragraph.
198+
"""
199+
def test_arg1(arg1):
200+
pass
201+
'''
202+
)
203+
204+
result = pytester.runpytest("--fixtures-per-test", p)
205+
assert result.ret == 0
206+
207+
result.stdout.fnmatch_lines(
208+
[
209+
"*fixtures used by test_arg1*",
210+
"*(test_multiline_docstring_in_module.py:13)*",
211+
"arg1 -- test_multiline_docstring_in_module.py:3",
212+
" Docstring content that spans across multiple lines,",
213+
" through second line,",
214+
" and through third line.",
215+
]
216+
)
217+
218+
219+
def test_verbose_include_multiline_docstring(pytester: Pytester) -> None:
220+
p = pytester.makepyfile(
221+
'''
222+
import pytest
223+
@pytest.fixture
224+
def arg1():
225+
"""Docstring content that spans across multiple lines,
226+
through second line,
227+
and through third line.
228+
229+
Docstring content that extends into a second paragraph.
230+
231+
Docstring content that extends into a third paragraph.
232+
"""
233+
def test_arg1(arg1):
234+
pass
235+
'''
236+
)
237+
238+
result = pytester.runpytest("--fixtures-per-test", "-v", p)
239+
assert result.ret == 0
240+
241+
result.stdout.fnmatch_lines(
242+
[
243+
"*fixtures used by test_arg1*",
244+
"*(test_verbose_include_multiline_docstring.py:13)*",
245+
"arg1 -- test_verbose_include_multiline_docstring.py:3",
246+
" Docstring content that spans across multiple lines,",
247+
" through second line,",
248+
" and through third line.",
249+
" ",
250+
" Docstring content that extends into a second paragraph.",
251+
" ",
252+
" Docstring content that extends into a third paragraph.",
253+
]
254+
)

0 commit comments

Comments
 (0)