diff --git a/_pytest/python.py b/_pytest/python.py index 9a504f6d8..ca076aa5f 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1014,16 +1014,26 @@ def _showfixtures_main(config, session): fm = session._fixturemanager available = [] + seen = set() + for argname, fixturedefs in fm._arg2fixturedefs.items(): assert fixturedefs is not None if not fixturedefs: continue for fixturedef in fixturedefs: loc = getlocation(fixturedef.func, curdir) + fixture_argname = fixturedef.argname + # invocation-scoped fixtures have argname in the form + # ":" (for example: "monkeypatch:session"). + if ':' in fixture_argname: + fixture_argname = fixture_argname.split(':')[0] + if (fixture_argname, loc) in seen: + continue + seen.add((fixture_argname, loc)) available.append((len(fixturedef.baseid), fixturedef.func.__module__, curdir.bestrelpath(loc), - fixturedef.argname, fixturedef)) + fixture_argname, fixturedef)) available.sort() currentmodule = None diff --git a/testing/python/fixture.py b/testing/python/fixture.py index efe15ae6b..22344efb9 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -2725,6 +2725,13 @@ class TestShowFixtures: Hi from test module ''') + def test_show_invocation_fixtures(self, testdir): + """py.test --fixtures should display invocation-scoped fixtures once. + """ + result = testdir.runpytest("--fixtures") + result.stdout.fnmatch_lines('''monkeypatch''') + assert 'monkeypatch:session' not in result.stdout.str() + @pytest.mark.parametrize('flavor', ['fixture', 'yield_fixture']) class TestContextManagerFixtureFuncs: