From 0659796a199e58fd6520a4a806bfff04afd8488e Mon Sep 17 00:00:00 2001 From: Warren Date: Sun, 17 Mar 2024 16:24:20 +1100 Subject: [PATCH] test(fixtures-per-test): exclude pseudo fixture output Adds a test suite to validate that --fixtures-per-test behaves as intuitively as possible for new users by excluding counter-intuitive output: the pseudo fixtures that result from directly parametrizing a test with ``@pytest.mark.parametrize``. The test suite further validates that fixtures which have been parametrized, either by direct or indirect means, are retained in the --fixtures-per-test output. --- testing/python/show_fixtures_per_test.py | 74 +++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/testing/python/show_fixtures_per_test.py b/testing/python/show_fixtures_per_test.py index f756dca41..f38bc4e2f 100644 --- a/testing/python/show_fixtures_per_test.py +++ b/testing/python/show_fixtures_per_test.py @@ -1,7 +1,7 @@ from _pytest.pytester import Pytester -def test_no_items_should_not_show_output(pytester: Pytester) -> None: +def test_should_show_no_ouput_when_zero_items(pytester: Pytester) -> None: result = pytester.runpytest("--fixtures-per-test") result.stdout.no_fnmatch_line("*fixtures used by*") assert result.ret == 0 @@ -252,3 +252,75 @@ def test_verbose_include_multiline_docstring(pytester: Pytester) -> None: " Docstring content that extends into a third paragraph.", ] ) + + +def test_should_not_show_pseudo_fixtures(pytester: Pytester) -> None: + """A fixture is considered pseudo if it was directly created using the + @pytest.mark.parametrize decorator as part of internal pytest mechanisms + to manage batch execution. These fixtures should not be included in the + output because they don't satisfy user expectations for how fixtures are + created and used.""" + + p = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("x", [1]) + def test_pseudo_fixture(x): + pass + """ + ) + result = pytester.runpytest("--fixtures-per-test", p) + result.stdout.no_fnmatch_line("*fixtures used by*") + assert result.ret == 0 + + +def test_should_show_parametrized_fixtures_used_by_test(pytester: Pytester) -> None: + """A fixture with parameters should be included if it was created using + the @pytest.fixture decorator, including those that are indirectly + parametrized.""" + p = pytester.makepyfile( + ''' + import pytest + + @pytest.fixture(params=['a', 'b']) + def directly(request): + """parametrized fixture""" + return request.param + + @pytest.fixture + def indirectly(request): + """indirectly parametrized fixture""" + return request.param + + def test_parametrized_fixture(directly): + pass + + @pytest.mark.parametrize("indirectly", ["a", "b"], indirect=True) + def test_indirectly_parametrized(indirectly): + pass + ''' + ) + result = pytester.runpytest("--fixtures-per-test", p) + assert result.ret == 0 + + expected_matches_for_parametrized_test = [ + "*fixtures used by test_parametrized_fixture*", + "*(test_should_show_parametrized_fixtures_used_by_test.py:14)*", + "directly -- test_should_show_parametrized_fixtures_used_by_test.py:4", + " parametrized fixture", + ] + + expected_matches_for_indirectly_parametrized_test = [ + "*fixtures used by test_indirectly_parametrized*", + "*(test_should_show_parametrized_fixtures_used_by_test.py:17)*", + "indirectly -- test_should_show_parametrized_fixtures_used_by_test.py:9", + " indirectly parametrized fixture", + ] + + expected_matches = ( + expected_matches_for_parametrized_test * 2 + + expected_matches_for_indirectly_parametrized_test * 2 + ) + + result.stdout.fnmatch_lines(expected_matches)