| """Test correct setup/teardowns at module, class, and instance level.""" |
| from typing import List |
| |
| import pytest |
| |
| |
| def test_module_and_function_setup(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| modlevel = [] |
| def setup_module(module): |
| assert not modlevel |
| module.modlevel.append(42) |
| |
| def teardown_module(module): |
| modlevel.pop() |
| |
| def setup_function(function): |
| function.answer = 17 |
| |
| def teardown_function(function): |
| del function.answer |
| |
| def test_modlevel(): |
| assert modlevel[0] == 42 |
| assert test_modlevel.answer == 17 |
| |
| class TestFromClass(object): |
| def test_module(self): |
| assert modlevel[0] == 42 |
| assert not hasattr(test_modlevel, 'answer') |
| """ |
| ) |
| rep = reprec.matchreport("test_modlevel") |
| assert rep.passed |
| rep = reprec.matchreport("test_module") |
| assert rep.passed |
| |
| |
| def test_module_setup_failure_no_teardown(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| values = [] |
| def setup_module(module): |
| values.append(1) |
| 0/0 |
| |
| def test_nothing(): |
| pass |
| |
| def teardown_module(module): |
| values.append(2) |
| """ |
| ) |
| reprec.assertoutcome(failed=1) |
| calls = reprec.getcalls("pytest_runtest_setup") |
| assert calls[0].item.module.values == [1] |
| |
| |
| def test_setup_function_failure_no_teardown(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| modlevel = [] |
| def setup_function(function): |
| modlevel.append(1) |
| 0/0 |
| |
| def teardown_function(module): |
| modlevel.append(2) |
| |
| def test_func(): |
| pass |
| """ |
| ) |
| calls = reprec.getcalls("pytest_runtest_setup") |
| assert calls[0].item.module.modlevel == [1] |
| |
| |
| def test_class_setup(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| class TestSimpleClassSetup(object): |
| clslevel = [] |
| def setup_class(cls): |
| cls.clslevel.append(23) |
| |
| def teardown_class(cls): |
| cls.clslevel.pop() |
| |
| def test_classlevel(self): |
| assert self.clslevel[0] == 23 |
| |
| class TestInheritedClassSetupStillWorks(TestSimpleClassSetup): |
| def test_classlevel_anothertime(self): |
| assert self.clslevel == [23] |
| |
| def test_cleanup(): |
| assert not TestSimpleClassSetup.clslevel |
| assert not TestInheritedClassSetupStillWorks.clslevel |
| """ |
| ) |
| reprec.assertoutcome(passed=1 + 2 + 1) |
| |
| |
| def test_class_setup_failure_no_teardown(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| class TestSimpleClassSetup(object): |
| clslevel = [] |
| def setup_class(cls): |
| 0/0 |
| |
| def teardown_class(cls): |
| cls.clslevel.append(1) |
| |
| def test_classlevel(self): |
| pass |
| |
| def test_cleanup(): |
| assert not TestSimpleClassSetup.clslevel |
| """ |
| ) |
| reprec.assertoutcome(failed=1, passed=1) |
| |
| |
| def test_method_setup(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| class TestSetupMethod(object): |
| def setup_method(self, meth): |
| self.methsetup = meth |
| def teardown_method(self, meth): |
| del self.methsetup |
| |
| def test_some(self): |
| assert self.methsetup == self.test_some |
| |
| def test_other(self): |
| assert self.methsetup == self.test_other |
| """ |
| ) |
| reprec.assertoutcome(passed=2) |
| |
| |
| def test_method_setup_failure_no_teardown(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| class TestMethodSetup(object): |
| clslevel = [] |
| def setup_method(self, method): |
| self.clslevel.append(1) |
| 0/0 |
| |
| def teardown_method(self, method): |
| self.clslevel.append(2) |
| |
| def test_method(self): |
| pass |
| |
| def test_cleanup(): |
| assert TestMethodSetup.clslevel == [1] |
| """ |
| ) |
| reprec.assertoutcome(failed=1, passed=1) |
| |
| |
| def test_method_setup_uses_fresh_instances(testdir): |
| reprec = testdir.inline_runsource( |
| """ |
| class TestSelfState1(object): |
| memory = [] |
| def test_hello(self): |
| self.memory.append(self) |
| |
| def test_afterhello(self): |
| assert self != self.memory[0] |
| """ |
| ) |
| reprec.assertoutcome(passed=2, failed=0) |
| |
| |
| def test_setup_that_skips_calledagain(testdir): |
| p = testdir.makepyfile( |
| """ |
| import pytest |
| def setup_module(mod): |
| pytest.skip("x") |
| def test_function1(): |
| pass |
| def test_function2(): |
| pass |
| """ |
| ) |
| reprec = testdir.inline_run(p) |
| reprec.assertoutcome(skipped=2) |
| |
| |
| def test_setup_fails_again_on_all_tests(testdir): |
| p = testdir.makepyfile( |
| """ |
| import pytest |
| def setup_module(mod): |
| raise ValueError(42) |
| def test_function1(): |
| pass |
| def test_function2(): |
| pass |
| """ |
| ) |
| reprec = testdir.inline_run(p) |
| reprec.assertoutcome(failed=2) |
| |
| |
| def test_setup_funcarg_setup_when_outer_scope_fails(testdir): |
| p = testdir.makepyfile( |
| """ |
| import pytest |
| def setup_module(mod): |
| raise ValueError(42) |
| @pytest.fixture |
| def hello(request): |
| raise ValueError("xyz43") |
| def test_function1(hello): |
| pass |
| def test_function2(hello): |
| pass |
| """ |
| ) |
| result = testdir.runpytest(p) |
| result.stdout.fnmatch_lines( |
| [ |
| "*function1*", |
| "*ValueError*42*", |
| "*function2*", |
| "*ValueError*42*", |
| "*2 errors*", |
| ] |
| ) |
| result.stdout.no_fnmatch_line("*xyz43*") |
| |
| |
| @pytest.mark.parametrize("arg", ["", "arg"]) |
| def test_setup_teardown_function_level_with_optional_argument( |
| testdir, monkeypatch, arg: str, |
| ) -> None: |
| """Parameter to setup/teardown xunit-style functions parameter is now optional (#1728).""" |
| import sys |
| |
| trace_setups_teardowns = [] # type: List[str] |
| monkeypatch.setattr( |
| sys, "trace_setups_teardowns", trace_setups_teardowns, raising=False |
| ) |
| p = testdir.makepyfile( |
| """ |
| import pytest |
| import sys |
| |
| trace = sys.trace_setups_teardowns.append |
| |
| def setup_module({arg}): trace('setup_module') |
| def teardown_module({arg}): trace('teardown_module') |
| |
| def setup_function({arg}): trace('setup_function') |
| def teardown_function({arg}): trace('teardown_function') |
| |
| def test_function_1(): pass |
| def test_function_2(): pass |
| |
| class Test(object): |
| def setup_method(self, {arg}): trace('setup_method') |
| def teardown_method(self, {arg}): trace('teardown_method') |
| |
| def test_method_1(self): pass |
| def test_method_2(self): pass |
| """.format( |
| arg=arg |
| ) |
| ) |
| result = testdir.inline_run(p) |
| result.assertoutcome(passed=4) |
| |
| expected = [ |
| "setup_module", |
| "setup_function", |
| "teardown_function", |
| "setup_function", |
| "teardown_function", |
| "setup_method", |
| "teardown_method", |
| "setup_method", |
| "teardown_method", |
| "teardown_module", |
| ] |
| assert trace_setups_teardowns == expected |