mirror of https://github.com/pytest-dev/pytest.git
[8.2.x] unittest: fix class instances no longer released on test teardown since pytest 8.2.0
This commit is contained in:
parent
558e4fa71a
commit
f7358aec28
|
@ -0,0 +1 @@
|
||||||
|
Fix a regression in pytest 8.2.0 where unittest class instances (a fresh one is created for each test) were not released promptly on test teardown but only on session teardown.
|
|
@ -212,11 +212,12 @@ class TestCaseFunction(Function):
|
||||||
super().setup()
|
super().setup()
|
||||||
|
|
||||||
def teardown(self) -> None:
|
def teardown(self) -> None:
|
||||||
super().teardown()
|
|
||||||
if self._explicit_tearDown is not None:
|
if self._explicit_tearDown is not None:
|
||||||
self._explicit_tearDown()
|
self._explicit_tearDown()
|
||||||
self._explicit_tearDown = None
|
self._explicit_tearDown = None
|
||||||
self._obj = None
|
self._obj = None
|
||||||
|
self._instance = None
|
||||||
|
super().teardown()
|
||||||
|
|
||||||
def startTest(self, testcase: "unittest.TestCase") -> None:
|
def startTest(self, testcase: "unittest.TestCase") -> None:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
# mypy: allow-untyped-defs
|
# mypy: allow-untyped-defs
|
||||||
import gc
|
|
||||||
import sys
|
import sys
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
@ -192,30 +191,35 @@ def test_teardown(pytester: Pytester) -> None:
|
||||||
def test_teardown_issue1649(pytester: Pytester) -> None:
|
def test_teardown_issue1649(pytester: Pytester) -> None:
|
||||||
"""
|
"""
|
||||||
Are TestCase objects cleaned up? Often unittest TestCase objects set
|
Are TestCase objects cleaned up? Often unittest TestCase objects set
|
||||||
attributes that are large and expensive during setUp.
|
attributes that are large and expensive during test run or setUp.
|
||||||
|
|
||||||
The TestCase will not be cleaned up if the test fails, because it
|
The TestCase will not be cleaned up if the test fails, because it
|
||||||
would then exist in the stackframe.
|
would then exist in the stackframe.
|
||||||
|
|
||||||
|
Regression test for #1649 (see also #12367).
|
||||||
"""
|
"""
|
||||||
testpath = pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
import unittest
|
import unittest
|
||||||
class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
|
import gc
|
||||||
def setUp(self):
|
|
||||||
self.an_expensive_object = 1
|
|
||||||
def test_demo(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
"""
|
class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
|
||||||
|
def test_expensive(self):
|
||||||
|
self.an_expensive_obj = object()
|
||||||
|
|
||||||
|
def test_is_it_still_alive(self):
|
||||||
|
gc.collect()
|
||||||
|
for obj in gc.get_objects():
|
||||||
|
if type(obj).__name__ == "TestCaseObjectsShouldBeCleanedUp":
|
||||||
|
assert not hasattr(obj, "an_expensive_obj")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
assert False, "Could not find TestCaseObjectsShouldBeCleanedUp instance"
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
pytester.inline_run("-s", testpath)
|
result = pytester.runpytest()
|
||||||
gc.collect()
|
assert result.ret == ExitCode.OK
|
||||||
|
|
||||||
# Either already destroyed, or didn't run setUp.
|
|
||||||
for obj in gc.get_objects():
|
|
||||||
if type(obj).__name__ == "TestCaseObjectsShouldBeCleanedUp":
|
|
||||||
assert not hasattr(obj, "an_expensive_obj")
|
|
||||||
|
|
||||||
|
|
||||||
def test_unittest_skip_issue148(pytester: Pytester) -> None:
|
def test_unittest_skip_issue148(pytester: Pytester) -> None:
|
||||||
|
|
Loading…
Reference in New Issue