From 9e759010d9e9bf6ff10766c54f37bdb6ce1266c2 Mon Sep 17 00:00:00 2001 From: JoshKarpel Date: Sun, 17 Nov 2019 16:45:42 -0600 Subject: [PATCH 1/4] resolve #2049 --- src/_pytest/setupplan.py | 3 +- testing/python/setup_plan.py | 103 +++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/_pytest/setupplan.py b/src/_pytest/setupplan.py index 697746f20..6fdd3aed0 100644 --- a/src/_pytest/setupplan.py +++ b/src/_pytest/setupplan.py @@ -16,7 +16,8 @@ def pytest_addoption(parser): def pytest_fixture_setup(fixturedef, request): # Will return a dummy fixture if the setuponly option is provided. if request.config.option.setupplan: - fixturedef.cached_result = (None, None, None) + my_cache_key = fixturedef.cache_key(request) + fixturedef.cached_result = (None, my_cache_key, None) return fixturedef.cached_result diff --git a/testing/python/setup_plan.py b/testing/python/setup_plan.py index e323ba240..8ff8bfc45 100644 --- a/testing/python/setup_plan.py +++ b/testing/python/setup_plan.py @@ -17,3 +17,106 @@ def test_show_fixtures_and_test(testdir, dummy_yaml_custom_test): result.stdout.fnmatch_lines( ["*SETUP F arg*", "*test_arg (fixtures used: arg)", "*TEARDOWN F arg*"] ) + + +def test_show_multi_test_fixture_setup_and_teardown_correctly_simple(testdir): + """ + Verify that when a fixture lives for longer than a single test, --setup-plan + correctly displays the SETUP/TEARDOWN indicators the right number of times. + + As reported in https://github.com/pytest-dev/pytest/issues/2049 + --setup-plan was showing SETUP/TEARDOWN on every test, even when the fixture + should persist through multiple tests. + + (Note that this bug never affected actual test execution, which used the + correct fixture lifetimes. It was purely a display bug for --setup-plan, and + did not affect the related --setup-show or --setup-only.) + """ + testdir.makepyfile( + """ + import pytest + + @pytest.fixture(scope = 'class') + def fix(): + return object() + + class TestClass: + def test_one(self, fix): + assert False + + def test_two(self, fix): + assert False + """ + ) + + result = testdir.runpytest("--setup-plan") + assert result.ret == 0 + + setup_fragment = "SETUP C fix" + setup_count = 0 + + teardown_fragment = "TEARDOWN C fix" + teardown_count = 0 + + for line in result.stdout.lines: + if setup_fragment in line: + setup_count += 1 + if teardown_fragment in line: + teardown_count += 1 + + # before the fix this tests, there would have been a setup/teardown + # message for each test, so the counts would each have been 2 + assert setup_count == 1 + assert teardown_count == 1 + + +def test_show_multi_test_fixture_setup_and_teardown_same_as_setup_show(testdir): + """ + Verify that SETUP/TEARDOWN messages match what comes out of --setup-show. + """ + testdir.makepyfile( + """ + import pytest + + @pytest.fixture(scope = 'session') + def sess(): + return True + + @pytest.fixture(scope = 'module') + def mod(): + return True + + @pytest.fixture(scope = 'class') + def cls(): + return True + + @pytest.fixture(scope = 'function') + def func(): + return True + + + def test_outside(sess, mod, cls, func): + assert True + + + class TestCls: + def test_one(self, sess, mod, cls, func): + assert True + + def test_two(self, sess, mod, cls, func): + assert True + """ + ) + + plan_result = testdir.runpytest("--setup-plan") + show_result = testdir.runpytest("--setup-show") + + # the number and text of these lines should be identical + plan_lines = [ + l for l in plan_result.stdout.lines if "SETUP" in l or "TEARDOWN" in l + ] + show_lines = [ + l for l in show_result.stdout.lines if "SETUP" in l or "TEARDOWN" in l + ] + + assert plan_lines == show_lines From 6dfd683a0c34535c79b6baccdc60d301c64b4f76 Mon Sep 17 00:00:00 2001 From: JoshKarpel Date: Sun, 17 Nov 2019 16:47:09 -0600 Subject: [PATCH 2/4] changelog entry for #2049 --- AUTHORS | 1 + changelog/2049.bugfix.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/2049.bugfix.rst diff --git a/AUTHORS b/AUTHORS index d0e584f63..b9e6f7271 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,6 +128,7 @@ Jeff Widman Jenni Rinker John Eddie Ayson John Towler +Josh Karpel Jon Sonesen Jonas Obrist Jordan Guymon diff --git a/changelog/2049.bugfix.rst b/changelog/2049.bugfix.rst new file mode 100644 index 000000000..395396bd3 --- /dev/null +++ b/changelog/2049.bugfix.rst @@ -0,0 +1 @@ +Fix ``-setup-plan`` showing inaccurate information about fixture lifetimes. From 1e3be8ada4585ba279cfc24be8c3b09b25213804 Mon Sep 17 00:00:00 2001 From: JoshKarpel Date: Sun, 17 Nov 2019 17:14:17 -0600 Subject: [PATCH 3/4] fix whitespace issues in tests for #2049 --- testing/python/setup_plan.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/testing/python/setup_plan.py b/testing/python/setup_plan.py index 8ff8bfc45..a44474dd1 100644 --- a/testing/python/setup_plan.py +++ b/testing/python/setup_plan.py @@ -35,15 +35,12 @@ def test_show_multi_test_fixture_setup_and_teardown_correctly_simple(testdir): testdir.makepyfile( """ import pytest - @pytest.fixture(scope = 'class') def fix(): return object() - class TestClass: def test_one(self, fix): assert False - def test_two(self, fix): assert False """ @@ -77,32 +74,23 @@ def test_show_multi_test_fixture_setup_and_teardown_same_as_setup_show(testdir): testdir.makepyfile( """ import pytest - @pytest.fixture(scope = 'session') def sess(): return True - @pytest.fixture(scope = 'module') def mod(): return True - @pytest.fixture(scope = 'class') def cls(): return True - @pytest.fixture(scope = 'function') def func(): return True - - def test_outside(sess, mod, cls, func): assert True - - class TestCls: def test_one(self, sess, mod, cls, func): assert True - def test_two(self, sess, mod, cls, func): assert True """ From 46ffdf0e3a98bbb6ecb2393ee706ed8250f56ade Mon Sep 17 00:00:00 2001 From: Josh Karpel Date: Sun, 17 Nov 2019 17:17:47 -0600 Subject: [PATCH 4/4] Update AUTHORS --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index b9e6f7271..1f136d83e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,13 +128,13 @@ Jeff Widman Jenni Rinker John Eddie Ayson John Towler -Josh Karpel Jon Sonesen Jonas Obrist Jordan Guymon Jordan Moldow Jordan Speicher Joseph Hunkeler +Josh Karpel Joshua Bronson Jurko Gospodnetić Justyna Janczyszyn