Skip to content

Commit f7358ae

Browse files
bluetechpytestbot
authored andcommitted
[8.2.x] unittest: fix class instances no longer released on test teardown since pytest 8.2.0
1 parent 558e4fa commit f7358ae

File tree

3 files changed

+23
-17
lines changed

3 files changed

+23
-17
lines changed

changelog/12367.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

src/_pytest/unittest.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,12 @@ def setup(self) -> None:
212212
super().setup()
213213

214214
def teardown(self) -> None:
215-
super().teardown()
216215
if self._explicit_tearDown is not None:
217216
self._explicit_tearDown()
218217
self._explicit_tearDown = None
219218
self._obj = None
219+
self._instance = None
220+
super().teardown()
220221

221222
def startTest(self, testcase: "unittest.TestCase") -> None:
222223
pass

testing/test_unittest.py

+20-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# mypy: allow-untyped-defs
2-
import gc
32
import sys
43
from typing import List
54

@@ -192,30 +191,35 @@ def test_check(self):
192191
def test_teardown_issue1649(pytester: Pytester) -> None:
193192
"""
194193
Are TestCase objects cleaned up? Often unittest TestCase objects set
195-
attributes that are large and expensive during setUp.
194+
attributes that are large and expensive during test run or setUp.
196195
197196
The TestCase will not be cleaned up if the test fails, because it
198197
would then exist in the stackframe.
198+
199+
Regression test for #1649 (see also #12367).
199200
"""
200-
testpath = pytester.makepyfile(
201+
pytester.makepyfile(
201202
"""
202203
import unittest
203-
class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
204-
def setUp(self):
205-
self.an_expensive_object = 1
206-
def test_demo(self):
207-
pass
204+
import gc
208205
209-
"""
206+
class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
207+
def test_expensive(self):
208+
self.an_expensive_obj = object()
209+
210+
def test_is_it_still_alive(self):
211+
gc.collect()
212+
for obj in gc.get_objects():
213+
if type(obj).__name__ == "TestCaseObjectsShouldBeCleanedUp":
214+
assert not hasattr(obj, "an_expensive_obj")
215+
break
216+
else:
217+
assert False, "Could not find TestCaseObjectsShouldBeCleanedUp instance"
218+
"""
210219
)
211220

212-
pytester.inline_run("-s", testpath)
213-
gc.collect()
214-
215-
# Either already destroyed, or didn't run setUp.
216-
for obj in gc.get_objects():
217-
if type(obj).__name__ == "TestCaseObjectsShouldBeCleanedUp":
218-
assert not hasattr(obj, "an_expensive_obj")
221+
result = pytester.runpytest()
222+
assert result.ret == ExitCode.OK
219223

220224

221225
def test_unittest_skip_issue148(pytester: Pytester) -> None:

0 commit comments

Comments
 (0)