From 5ea8969461ecaff9b30c5ac3416cac32da91eeb7 Mon Sep 17 00:00:00 2001 From: Tobias Deiminger Date: Thu, 16 Dec 2021 21:03:49 +0100 Subject: [PATCH] Add and adapt tests Add tests to assert #8914 is fixed. Tests assures that both reordering and caching work as intended, and demonstrates how one can use parameter ids to decide about equality. Adapting issue_519.checked_order is not cheating. See our discussion at https://github.com/pytest-dev/pytest/pull/9350#pullrequestreview-819514238 --- testing/example_scripts/issue_519.py | 4 +-- testing/python/fixtures.py | 53 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/testing/example_scripts/issue_519.py b/testing/example_scripts/issue_519.py index e44367fca04..73437ef7bdb 100644 --- a/testing/example_scripts/issue_519.py +++ b/testing/example_scripts/issue_519.py @@ -22,13 +22,13 @@ def checked_order(): assert order == [ ("issue_519.py", "fix1", "arg1v1"), ("test_one[arg1v1-arg2v1]", "fix2", "arg2v1"), - ("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"), ("test_one[arg1v1-arg2v2]", "fix2", "arg2v2"), + ("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"), ("test_two[arg1v1-arg2v2]", "fix2", "arg2v2"), ("issue_519.py", "fix1", "arg1v2"), ("test_one[arg1v2-arg2v1]", "fix2", "arg2v1"), - ("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"), ("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"), + ("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"), ("test_two[arg1v2-arg2v2]", "fix2", "arg2v2"), ] diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 3ce5cb34ddd..9ff8d3e9fe4 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1308,6 +1308,59 @@ def test2(no_eq): result = pytester.runpytest() result.stdout.fnmatch_lines(["*4 passed*"]) + @pytest.mark.parametrize( + ("parametrize1", "parametrize2"), + [ + ( + '"fix", [1, 2], indirect=True', + '"fix", [2, 1], indirect=True', + ), + ( + '"fix", [1, pytest.param({"data": 2}, id="2")], indirect=True', + '"fix", [pytest.param({"data": 2}, id="2"), 1], indirect=True', + ), + ( + '"fix", [{"data": 1}, {"data": 2}], indirect=True, ids=lambda d: MyEnum(d["data"])', + '"fix", [{"data": 2}, {"data": 1}], indirect=True, ids=lambda d: MyEnum(d["data"])', + ), + ( + '"fix", [{"data": 1}, {"data": 2}], indirect=True, ids=[1, "two"]', + '"fix", [{"data": 2}, {"data": 1}], indirect=True, ids=["two", 1]', + ), + ], + ) + def test_reorder_and_cache( + self, pytester: Pytester, parametrize1, parametrize2 + ) -> None: + """Test optimization for minimal setup/teardown with indirectly parametrized fixtures. See #8914, #9420.""" + pytester.makepyfile( + f""" + import pytest + from enum import Enum + class MyEnum(Enum): + Id1 = 1 + Id2 = 2 + @pytest.fixture(scope="session") + def fix(request): + value = request.param["data"] if isinstance(request.param, dict) else request.param + print(f'prepare foo-%s' % value) + yield value + print(f'teardown foo-%s' % value) + @pytest.mark.parametrize({parametrize1}) + def test1(fix): + pass + @pytest.mark.parametrize({parametrize2}) + def test2(fix): + pass + """ + ) + result = pytester.runpytest("-s") + output = result.stdout.str() + assert output.count("prepare foo-1") == 1 + assert output.count("prepare foo-2") == 1 + assert output.count("teardown foo-1") == 1 + assert output.count("teardown foo-2") == 1 + def test_funcarg_parametrized_and_used_twice(self, pytester: Pytester) -> None: pytester.makepyfile( """