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>
This commit is contained in:
		
							parent
							
								
									33c6ad5bf7
								
							
						
					
					
						commit
						c516dba69a
					
				| 
						 | 
					@ -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.
 | 
				
			||||||
| 
						 | 
					@ -1428,15 +1428,15 @@ def _show_fixtures_per_test(config: Config, session: Session) -> None:
 | 
				
			||||||
        argname = fixture_def.argname
 | 
					        argname = fixture_def.argname
 | 
				
			||||||
        if verbose <= 0 and argname.startswith("_"):
 | 
					        if verbose <= 0 and argname.startswith("_"):
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        if verbose > 0:
 | 
					        bestrel = get_best_relpath(fixture_def.func)
 | 
				
			||||||
            bestrel = get_best_relpath(fixture_def.func)
 | 
					        tw.write(f"{argname}", green=True)
 | 
				
			||||||
            funcargspec = f"{argname} -- {bestrel}"
 | 
					        tw.write(f" -- {bestrel}", yellow=True)
 | 
				
			||||||
        else:
 | 
					        tw.write("\n")
 | 
				
			||||||
            funcargspec = argname
 | 
					 | 
				
			||||||
        tw.line(funcargspec, green=True)
 | 
					 | 
				
			||||||
        fixture_doc = inspect.getdoc(fixture_def.func)
 | 
					        fixture_doc = inspect.getdoc(fixture_def.func)
 | 
				
			||||||
        if fixture_doc:
 | 
					        if fixture_doc:
 | 
				
			||||||
            write_docstring(tw, fixture_doc)
 | 
					            write_docstring(
 | 
				
			||||||
 | 
					                tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            tw.line("    no docstring available", red=True)
 | 
					            tw.line("    no docstring available", red=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1508,18 +1508,17 @@ def _showfixtures_main(config: Config, session: Session) -> None:
 | 
				
			||||||
                tw.line()
 | 
					                tw.line()
 | 
				
			||||||
                tw.sep("-", f"fixtures defined from {module}")
 | 
					                tw.sep("-", f"fixtures defined from {module}")
 | 
				
			||||||
                currentmodule = module
 | 
					                currentmodule = module
 | 
				
			||||||
        if verbose <= 0 and argname[0] == "_":
 | 
					        if verbose <= 0 and argname.startswith("_"):
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
        tw.write(argname, green=True)
 | 
					        tw.write(f"{argname}", green=True)
 | 
				
			||||||
        if fixturedef.scope != "function":
 | 
					        if fixturedef.scope != "function":
 | 
				
			||||||
            tw.write(" [%s scope]" % fixturedef.scope, cyan=True)
 | 
					            tw.write(" [%s scope]" % fixturedef.scope, cyan=True)
 | 
				
			||||||
        if verbose > 0:
 | 
					        tw.write(f" -- {bestrel}", yellow=True)
 | 
				
			||||||
            tw.write(" -- %s" % bestrel, yellow=True)
 | 
					 | 
				
			||||||
        tw.write("\n")
 | 
					        tw.write("\n")
 | 
				
			||||||
        loc = getlocation(fixturedef.func, str(curdir))
 | 
					        loc = getlocation(fixturedef.func, str(curdir))
 | 
				
			||||||
        doc = inspect.getdoc(fixturedef.func)
 | 
					        doc = inspect.getdoc(fixturedef.func)
 | 
				
			||||||
        if doc:
 | 
					        if doc:
 | 
				
			||||||
            write_docstring(tw, doc)
 | 
					            write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            tw.line(f"    {loc}: no docstring available", red=True)
 | 
					            tw.line(f"    {loc}: no docstring available", red=True)
 | 
				
			||||||
        tw.line()
 | 
					        tw.line()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3334,9 +3334,9 @@ class TestShowFixtures:
 | 
				
			||||||
        result = pytester.runpytest("--fixtures")
 | 
					        result = pytester.runpytest("--fixtures")
 | 
				
			||||||
        result.stdout.fnmatch_lines(
 | 
					        result.stdout.fnmatch_lines(
 | 
				
			||||||
            [
 | 
					            [
 | 
				
			||||||
                "tmp_path_factory [[]session scope[]]",
 | 
					                "tmp_path_factory [[]session scope[]] -- *tmpdir.py*",
 | 
				
			||||||
                "*for the test session*",
 | 
					                "*for the test session*",
 | 
				
			||||||
                "tmp_path",
 | 
					                "tmp_path -- *",
 | 
				
			||||||
                "*temporary directory*",
 | 
					                "*temporary directory*",
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -3367,9 +3367,9 @@ class TestShowFixtures:
 | 
				
			||||||
        result = pytester.runpytest("--fixtures", p)
 | 
					        result = pytester.runpytest("--fixtures", p)
 | 
				
			||||||
        result.stdout.fnmatch_lines(
 | 
					        result.stdout.fnmatch_lines(
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            *tmp_path
 | 
					            *tmp_path -- *
 | 
				
			||||||
            *fixtures defined from*
 | 
					            *fixtures defined from*
 | 
				
			||||||
            *arg1*
 | 
					            *arg1 -- test_show_fixtures_testmodule.py:6*
 | 
				
			||||||
            *hello world*
 | 
					            *hello world*
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -3429,10 +3429,10 @@ class TestShowFixtures:
 | 
				
			||||||
            textwrap.dedent(
 | 
					            textwrap.dedent(
 | 
				
			||||||
                """\
 | 
					                """\
 | 
				
			||||||
                * fixtures defined from test_show_fixtures_trimmed_doc *
 | 
					                * fixtures defined from test_show_fixtures_trimmed_doc *
 | 
				
			||||||
                arg2
 | 
					                arg2 -- test_show_fixtures_trimmed_doc.py:10
 | 
				
			||||||
                    line1
 | 
					                    line1
 | 
				
			||||||
                    line2
 | 
					                    line2
 | 
				
			||||||
                arg1
 | 
					                arg1 -- test_show_fixtures_trimmed_doc.py:3
 | 
				
			||||||
                    line1
 | 
					                    line1
 | 
				
			||||||
                    line2
 | 
					                    line2
 | 
				
			||||||
                """
 | 
					                """
 | 
				
			||||||
| 
						 | 
					@ -3458,7 +3458,7 @@ class TestShowFixtures:
 | 
				
			||||||
            textwrap.dedent(
 | 
					            textwrap.dedent(
 | 
				
			||||||
                """\
 | 
					                """\
 | 
				
			||||||
                * fixtures defined from test_show_fixtures_indented_doc *
 | 
					                * fixtures defined from test_show_fixtures_indented_doc *
 | 
				
			||||||
                fixture1
 | 
					                fixture1 -- test_show_fixtures_indented_doc.py:3
 | 
				
			||||||
                    line1
 | 
					                    line1
 | 
				
			||||||
                        indented line
 | 
					                        indented line
 | 
				
			||||||
                """
 | 
					                """
 | 
				
			||||||
| 
						 | 
					@ -3486,7 +3486,7 @@ class TestShowFixtures:
 | 
				
			||||||
            textwrap.dedent(
 | 
					            textwrap.dedent(
 | 
				
			||||||
                """\
 | 
					                """\
 | 
				
			||||||
                * fixtures defined from test_show_fixtures_indented_doc_first_line_unindented *
 | 
					                * fixtures defined from test_show_fixtures_indented_doc_first_line_unindented *
 | 
				
			||||||
                fixture1
 | 
					                fixture1 -- test_show_fixtures_indented_doc_first_line_unindented.py:3
 | 
				
			||||||
                    line1
 | 
					                    line1
 | 
				
			||||||
                    line2
 | 
					                    line2
 | 
				
			||||||
                        indented line
 | 
					                        indented line
 | 
				
			||||||
| 
						 | 
					@ -3514,7 +3514,7 @@ class TestShowFixtures:
 | 
				
			||||||
            textwrap.dedent(
 | 
					            textwrap.dedent(
 | 
				
			||||||
                """\
 | 
					                """\
 | 
				
			||||||
                * fixtures defined from test_show_fixtures_indented_in_class *
 | 
					                * fixtures defined from test_show_fixtures_indented_in_class *
 | 
				
			||||||
                fixture1
 | 
					                fixture1 -- test_show_fixtures_indented_in_class.py:4
 | 
				
			||||||
                    line1
 | 
					                    line1
 | 
				
			||||||
                    line2
 | 
					                    line2
 | 
				
			||||||
                        indented line
 | 
					                        indented line
 | 
				
			||||||
| 
						 | 
					@ -3554,11 +3554,11 @@ class TestShowFixtures:
 | 
				
			||||||
        result.stdout.fnmatch_lines(
 | 
					        result.stdout.fnmatch_lines(
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            * fixtures defined from test_a *
 | 
					            * fixtures defined from test_a *
 | 
				
			||||||
            fix_a
 | 
					            fix_a -- test_a.py:4
 | 
				
			||||||
                Fixture A
 | 
					                Fixture A
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            * fixtures defined from test_b *
 | 
					            * fixtures defined from test_b *
 | 
				
			||||||
            fix_b
 | 
					            fix_b -- test_b.py:4
 | 
				
			||||||
                Fixture B
 | 
					                Fixture B
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -3594,11 +3594,11 @@ class TestShowFixtures:
 | 
				
			||||||
        result.stdout.fnmatch_lines(
 | 
					        result.stdout.fnmatch_lines(
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            * fixtures defined from conftest *
 | 
					            * fixtures defined from conftest *
 | 
				
			||||||
            arg1
 | 
					            arg1 -- conftest.py:3
 | 
				
			||||||
                Hello World in conftest.py
 | 
					                Hello World in conftest.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            * fixtures defined from test_show_fixtures_with_same_name *
 | 
					            * fixtures defined from test_show_fixtures_with_same_name *
 | 
				
			||||||
            arg1
 | 
					            arg1 -- test_show_fixtures_with_same_name.py:3
 | 
				
			||||||
                Hi from test module
 | 
					                Hi from test module
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ def test_fixtures_in_module(pytester: Pytester) -> None:
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
            "*fixtures used by test_arg1*",
 | 
					            "*fixtures used by test_arg1*",
 | 
				
			||||||
            "*(test_fixtures_in_module.py:9)*",
 | 
					            "*(test_fixtures_in_module.py:9)*",
 | 
				
			||||||
            "arg1",
 | 
					            "arg1 -- test_fixtures_in_module.py:6",
 | 
				
			||||||
            "    arg1 docstring",
 | 
					            "    arg1 docstring",
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					@ -68,17 +68,16 @@ def test_fixtures_in_conftest(pytester: Pytester) -> None:
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
            "*fixtures used by test_arg2*",
 | 
					            "*fixtures used by test_arg2*",
 | 
				
			||||||
            "*(test_fixtures_in_conftest.py:2)*",
 | 
					            "*(test_fixtures_in_conftest.py:2)*",
 | 
				
			||||||
            "arg2",
 | 
					            "arg2 -- conftest.py:6",
 | 
				
			||||||
            "    arg2 docstring",
 | 
					            "    arg2 docstring",
 | 
				
			||||||
            "*fixtures used by test_arg3*",
 | 
					            "*fixtures used by test_arg3*",
 | 
				
			||||||
            "*(test_fixtures_in_conftest.py:4)*",
 | 
					            "*(test_fixtures_in_conftest.py:4)*",
 | 
				
			||||||
            "arg1",
 | 
					            "arg1 -- conftest.py:3",
 | 
				
			||||||
            "    arg1 docstring",
 | 
					            "    arg1 docstring",
 | 
				
			||||||
            "arg2",
 | 
					            "arg2 -- conftest.py:6",
 | 
				
			||||||
            "    arg2 docstring",
 | 
					            "    arg2 docstring",
 | 
				
			||||||
            "arg3",
 | 
					            "arg3 -- conftest.py:9",
 | 
				
			||||||
            "    arg3",
 | 
					            "    arg3",
 | 
				
			||||||
            "    docstring",
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,9 +111,9 @@ def test_should_show_fixtures_used_by_test(pytester: Pytester) -> None:
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
            "*fixtures used by test_args*",
 | 
					            "*fixtures used by test_args*",
 | 
				
			||||||
            "*(test_should_show_fixtures_used_by_test.py:6)*",
 | 
					            "*(test_should_show_fixtures_used_by_test.py:6)*",
 | 
				
			||||||
            "arg1",
 | 
					            "arg1 -- test_should_show_fixtures_used_by_test.py:3",
 | 
				
			||||||
            "    arg1 from testmodule",
 | 
					            "    arg1 from testmodule",
 | 
				
			||||||
            "arg2",
 | 
					            "arg2 -- conftest.py:6",
 | 
				
			||||||
            "    arg2 from conftest",
 | 
					            "    arg2 from conftest",
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					@ -181,3 +180,75 @@ def test_doctest_items(pytester: Pytester) -> None:
 | 
				
			||||||
    assert result.ret == 0
 | 
					    assert result.ret == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    result.stdout.fnmatch_lines(["*collected 2 items*"])
 | 
					    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.",
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue