This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: unittest fails to properly destruct objects created during setUp if a test fails
Type: behavior Stage: resolved
Components: Windows Versions: Python 3.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: MCBama, paul.moore, r.david.murray, steve.dower, tim.golden, zach.ware
Priority: normal Keywords:

Created on 2017-08-22 22:26 by MCBama, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
test_bug.py MCBama, 2017-08-22 22:26 unittest showcasing the unexpected behavior
Messages (2)
msg300725 - (view) Author: Micah (MCBama) Date: 2017-08-22 22:26
When running the attached example test dummy objects are created during setUp and destructed at the end of a passing test but when a test fails the dummy object that was created in setUp fails to deconstruct. This leads to cascading errors when writing integration tests where having a "ghost" object sitting in the background and listening to messages is detrimental.

This behavior became apparent when I was writing integration tests making use of a signalling package so I pulled everything that wasn't base python to see if the bug was reproduced and it was. The object that failed to deconstruct when the test failed(0x000001CA971F6208) deconstructs at the end of the entire testcase while the object declared within the test function itself(0x000001CA971F62B0) deconstructs as soon as the test fails out.

The output of the test that I ran was this:

> python -m unittest test_bug.py


test_fail (test_bug.TestBug)
Created <test_bug.DummyClass object at 0x000001CA971F6208>
Created local <test_bug.DummyClass object at 0x000001CA971F62B0>
F
deleting <test_bug.DummyClass object at 0x000001CA971F62B0>


test_pass (test_bug.TestBug)
Created <test_bug.DummyClass object at 0x000001CA971F62B0>
.
deleting <test_bug.DummyClass object at 0x000001CA971F62B0>


test_passes (test_bug.TestBug)
Created <test_bug.DummyClass object at 0x000001CA971A5400>
.
deleting <test_bug.DummyClass object at 0x000001CA971A5400>

======================================================================
FAIL: test_fail (test_bug.TestBug)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Code\test_bug.py", line 27, in test_fail
    self.assertTrue(False)
AssertionError: False is not true

----------------------------------------------------------------------
Ran 3 tests in 0.004s

FAILED (failures=1)

deleting <test_bug.DummyClass object at 0x000001CA971F6208>
msg300730 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-08-22 23:20
GC cleanup is not guaranteed to be synchronous.  You are observing normal Python behavior here.  Cleanup does not happen until the TestCase instance is finalized (thus eliminating the self.dummy reference to your DummyClass).  In the case of passing tests, that is after the '.' is printed.  In the case of failing tests, that is after the failure is printed, which isn't until the failure summary is printed at after running all tests.

If it is important to you that DummyClass be finalized, you need to add an addCleanup call to your setUp method that will do whatever finalization you need done.  Including doing 'del self.dummy' (or self.dummy = None) if you need the reference to it gone...but depending on garbage collection is a bad idea, so if you are doing that there is probably something sub-optimal about your design.
History
Date User Action Args
2022-04-11 14:58:51adminsetgithub: 75444
2017-08-22 23:20:06r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg300730

resolution: not a bug
stage: resolved
2017-08-22 22:26:00MCBamacreate