2024-01-28 21:12:42 +08:00
|
|
|
# mypy: allow-untyped-defs
|
2020-07-18 17:35:13 +08:00
|
|
|
"""Test correct setup/teardowns at module, class, and instance level."""
|
2020-05-01 19:40:17 +08:00
|
|
|
from typing import List
|
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
from _pytest.pytester import Pytester
|
2016-07-15 08:28:59 +08:00
|
|
|
import pytest
|
|
|
|
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_module_and_function_setup(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2010-07-27 03:15:15 +08:00
|
|
|
"""
|
2008-08-16 23:26:59 +08:00
|
|
|
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
|
|
|
|
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestFromClass(object):
|
2008-08-16 23:26:59 +08:00
|
|
|
def test_module(self):
|
|
|
|
assert modlevel[0] == 42
|
2010-07-27 03:15:15 +08:00
|
|
|
assert not hasattr(test_modlevel, 'answer')
|
2008-08-16 23:26:59 +08:00
|
|
|
"""
|
|
|
|
)
|
2010-07-27 03:15:15 +08:00
|
|
|
rep = reprec.matchreport("test_modlevel")
|
|
|
|
assert rep.passed
|
|
|
|
rep = reprec.matchreport("test_module")
|
|
|
|
assert rep.passed
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_module_setup_failure_no_teardown(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2013-08-02 15:52:40 +08:00
|
|
|
"""
|
2017-11-04 23:17:20 +08:00
|
|
|
values = []
|
2013-08-02 15:52:40 +08:00
|
|
|
def setup_module(module):
|
2017-11-04 23:17:20 +08:00
|
|
|
values.append(1)
|
2013-08-02 15:52:40 +08:00
|
|
|
0/0
|
|
|
|
|
|
|
|
def test_nothing():
|
|
|
|
pass
|
|
|
|
|
|
|
|
def teardown_module(module):
|
2017-11-04 23:17:20 +08:00
|
|
|
values.append(2)
|
2013-08-02 15:52:40 +08:00
|
|
|
"""
|
|
|
|
)
|
|
|
|
reprec.assertoutcome(failed=1)
|
|
|
|
calls = reprec.getcalls("pytest_runtest_setup")
|
2017-11-04 23:17:20 +08:00
|
|
|
assert calls[0].item.module.values == [1]
|
2013-08-02 15:52:40 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_setup_function_failure_no_teardown(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2013-08-02 15:52:40 +08:00
|
|
|
"""
|
|
|
|
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]
|
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_class_setup(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2009-05-21 20:33:09 +08:00
|
|
|
"""
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestSimpleClassSetup(object):
|
2008-08-16 23:26:59 +08:00
|
|
|
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():
|
2010-07-27 03:15:15 +08:00
|
|
|
assert not TestSimpleClassSetup.clslevel
|
2008-08-16 23:26:59 +08:00
|
|
|
assert not TestInheritedClassSetupStillWorks.clslevel
|
|
|
|
"""
|
|
|
|
)
|
2017-07-17 07:25:08 +08:00
|
|
|
reprec.assertoutcome(passed=1 + 2 + 1)
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_class_setup_failure_no_teardown(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2013-08-02 15:52:40 +08:00
|
|
|
"""
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestSimpleClassSetup(object):
|
2013-08-02 15:52:40 +08:00
|
|
|
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)
|
2009-07-08 22:41:30 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_method_setup(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2009-05-21 20:33:09 +08:00
|
|
|
"""
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestSetupMethod(object):
|
2008-08-16 23:26:59 +08:00
|
|
|
def setup_method(self, meth):
|
2010-07-27 03:15:15 +08:00
|
|
|
self.methsetup = meth
|
2008-08-16 23:26:59 +08:00
|
|
|
def teardown_method(self, meth):
|
2010-07-27 03:15:15 +08:00
|
|
|
del self.methsetup
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def test_some(self):
|
2010-07-27 03:15:15 +08:00
|
|
|
assert self.methsetup == self.test_some
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def test_other(self):
|
|
|
|
assert self.methsetup == self.test_other
|
|
|
|
"""
|
|
|
|
)
|
2009-05-21 20:33:09 +08:00
|
|
|
reprec.assertoutcome(passed=2)
|
2010-07-27 03:15:15 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_method_setup_failure_no_teardown(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2013-08-02 15:52:40 +08:00
|
|
|
"""
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestMethodSetup(object):
|
2013-08-02 15:52:40 +08:00
|
|
|
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)
|
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_method_setup_uses_fresh_instances(pytester: Pytester) -> None:
|
|
|
|
reprec = pytester.inline_runsource(
|
2009-05-21 20:33:09 +08:00
|
|
|
"""
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestSelfState1(object):
|
2009-08-07 00:15:21 +08:00
|
|
|
memory = []
|
2008-08-16 23:26:59 +08:00
|
|
|
def test_hello(self):
|
2009-08-07 00:15:21 +08:00
|
|
|
self.memory.append(self)
|
|
|
|
|
2008-08-16 23:26:59 +08:00
|
|
|
def test_afterhello(self):
|
2009-08-07 00:15:21 +08:00
|
|
|
assert self != self.memory[0]
|
2008-08-16 23:26:59 +08:00
|
|
|
"""
|
|
|
|
)
|
2009-08-07 00:15:21 +08:00
|
|
|
reprec.assertoutcome(passed=2, failed=0)
|
2009-04-05 03:06:20 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_setup_that_skips_calledagain(pytester: Pytester) -> None:
|
|
|
|
p = pytester.makepyfile(
|
2010-01-27 19:09:30 +08:00
|
|
|
"""
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
2010-01-27 19:09:30 +08:00
|
|
|
def setup_module(mod):
|
2010-11-18 05:12:16 +08:00
|
|
|
pytest.skip("x")
|
2010-01-27 19:09:30 +08:00
|
|
|
def test_function1():
|
|
|
|
pass
|
|
|
|
def test_function2():
|
|
|
|
pass
|
|
|
|
"""
|
|
|
|
)
|
2020-10-31 18:38:11 +08:00
|
|
|
reprec = pytester.inline_run(p)
|
2013-08-02 15:52:40 +08:00
|
|
|
reprec.assertoutcome(skipped=2)
|
2010-01-28 21:20:58 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_setup_fails_again_on_all_tests(pytester: Pytester) -> None:
|
|
|
|
p = pytester.makepyfile(
|
2010-01-28 21:20:58 +08:00
|
|
|
"""
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
2010-01-28 21:20:58 +08:00
|
|
|
def setup_module(mod):
|
|
|
|
raise ValueError(42)
|
|
|
|
def test_function1():
|
|
|
|
pass
|
|
|
|
def test_function2():
|
|
|
|
pass
|
|
|
|
"""
|
|
|
|
)
|
2020-10-31 18:38:11 +08:00
|
|
|
reprec = pytester.inline_run(p)
|
2013-08-02 15:52:40 +08:00
|
|
|
reprec.assertoutcome(failed=2)
|
2010-01-28 21:20:58 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2020-10-31 18:38:11 +08:00
|
|
|
def test_setup_funcarg_setup_when_outer_scope_fails(pytester: Pytester) -> None:
|
|
|
|
p = pytester.makepyfile(
|
2010-01-28 22:36:27 +08:00
|
|
|
"""
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
2010-01-28 22:36:27 +08:00
|
|
|
def setup_module(mod):
|
|
|
|
raise ValueError(42)
|
2016-07-12 09:03:53 +08:00
|
|
|
@pytest.fixture
|
|
|
|
def hello(request):
|
2010-04-21 20:46:41 +08:00
|
|
|
raise ValueError("xyz43")
|
2010-01-28 22:36:27 +08:00
|
|
|
def test_function1(hello):
|
|
|
|
pass
|
|
|
|
def test_function2(hello):
|
|
|
|
pass
|
|
|
|
"""
|
|
|
|
)
|
2020-10-31 18:38:11 +08:00
|
|
|
result = pytester.runpytest(p)
|
2010-01-28 22:36:27 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
|
|
|
"*function1*",
|
|
|
|
"*ValueError*42*",
|
|
|
|
"*function2*",
|
|
|
|
"*ValueError*42*",
|
2019-10-27 23:02:37 +08:00
|
|
|
"*2 errors*",
|
2010-01-28 22:36:27 +08:00
|
|
|
]
|
|
|
|
)
|
2019-10-06 01:18:51 +08:00
|
|
|
result.stdout.no_fnmatch_line("*xyz43*")
|
2016-07-15 08:28:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("arg", ["", "arg"])
|
|
|
|
def test_setup_teardown_function_level_with_optional_argument(
|
2020-12-30 17:56:09 +08:00
|
|
|
pytester: Pytester,
|
|
|
|
monkeypatch,
|
|
|
|
arg: str,
|
2020-05-01 19:40:17 +08:00
|
|
|
) -> None:
|
2020-07-18 17:35:13 +08:00
|
|
|
"""Parameter to setup/teardown xunit-style functions parameter is now optional (#1728)."""
|
2016-07-15 08:28:59 +08:00
|
|
|
import sys
|
2018-05-23 22:48:46 +08:00
|
|
|
|
2020-10-06 09:13:05 +08:00
|
|
|
trace_setups_teardowns: List[str] = []
|
2016-07-15 08:28:59 +08:00
|
|
|
monkeypatch.setattr(
|
|
|
|
sys, "trace_setups_teardowns", trace_setups_teardowns, raising=False
|
|
|
|
)
|
2020-10-31 18:38:11 +08:00
|
|
|
p = pytester.makepyfile(
|
2016-07-15 08:28:59 +08:00
|
|
|
f"""
|
|
|
|
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
|
|
|
|
|
2017-02-17 02:41:51 +08:00
|
|
|
class Test(object):
|
2016-07-15 08:28:59 +08:00
|
|
|
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
|
|
|
|
"""
|
2018-05-23 22:48:46 +08:00
|
|
|
)
|
2020-10-31 18:38:11 +08:00
|
|
|
result = pytester.inline_run(p)
|
2016-07-15 08:28:59 +08:00
|
|
|
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
|