Skip to content

Commit e46e653

Browse files
author
Dan Wandschneider
committed
Clean up unittest TestCase objects after tests are complete (#1649).
Fix #1649 Users of unittest style TestCases will create expensive objects in setUp. We should clean up TestCase instances that are lying around so that they don't fill up memory.
1 parent 07af307 commit e46e653

File tree

4 files changed

+31
-1
lines changed

4 files changed

+31
-1
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Christopher Gilling
3636
Daniel Grana
3737
Daniel Hahler
3838
Daniel Nuri
39+
Daniel Wandschneider
3940
Danielle Jenkins
4041
Dave Hunt
4142
David Díaz-Barquero

CHANGELOG.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
* Properly handle exceptions in ``multiprocessing`` tasks (`#1984`_).
2727
Thanks `@adborden`_ for the report and `@nicoddemus`_ for the PR.
2828

29-
*
29+
* Clean up unittest TestCase objects after tests are complete (`#1649`_).
30+
Thanks `@d_b_w`_ for the report and PR.
3031

3132
*
3233

@@ -38,13 +39,15 @@
3839
.. _@okulynyak: https://github.com/okulynyak
3940
.. _@matclab: https://github.com/matclab
4041
.. _@gdyuldin: https://github.com/gdyuldin
42+
.. _@d_b_w: https://github.com/d_b_w
4143

4244
.. _#442: https://github.com/pytest-dev/pytest/issues/442
4345
.. _#1976: https://github.com/pytest-dev/pytest/issues/1976
4446
.. _#1984: https://github.com/pytest-dev/pytest/issues/1984
4547
.. _#1998: https://github.com/pytest-dev/pytest/issues/1998
4648
.. _#2004: https://github.com/pytest-dev/pytest/issues/2004
4749
.. _#2005: https://github.com/pytest-dev/pytest/issues/2005
50+
.. _#1649: https://github.com/pytest-dev/pytest/issues/1649
4851

4952

5053
3.0.3

_pytest/unittest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ def _fix_unittest_skip_decorator(self):
9494
def teardown(self):
9595
if hasattr(self._testcase, 'teardown_method'):
9696
self._testcase.teardown_method(self._obj)
97+
# Allow garbage collection on TestCase instance attributes.
98+
self._testcase = None
99+
self._obj = None
97100

98101
def startTest(self, testcase):
99102
pass

testing/test_unittest.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from _pytest.main import EXIT_NOTESTSCOLLECTED
22
import pytest
3+
import gc
34

45
def test_simple_unittest(testdir):
56
testpath = testdir.makepyfile("""
@@ -134,6 +135,28 @@ def test_check(self):
134135
assert passed == 2
135136
assert passed + skipped + failed == 2
136137

138+
def test_teardown_issue1649(testdir):
139+
"""
140+
Are TestCase objects cleaned up? Often unittest TestCase objects set
141+
attributes that are large and expensive during setUp.
142+
143+
The TestCase will not be cleaned up if the test fails, because it
144+
would then exist in the stackframe.
145+
"""
146+
testpath = testdir.makepyfile("""
147+
import unittest
148+
class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
149+
def setUp(self):
150+
self.an_expensive_object = 1
151+
def test_demo(self):
152+
pass
153+
154+
""")
155+
testdir.inline_run("-s", testpath)
156+
gc.collect()
157+
for obj in gc.get_objects():
158+
assert type(obj).__name__ != 'TestCaseObjectsShouldBeCleanedUp'
159+
137160
@pytest.mark.skipif("sys.version_info < (2,7)")
138161
def test_unittest_skip_issue148(testdir):
139162
testpath = testdir.makepyfile("""

0 commit comments

Comments
 (0)