我想测试 Python 对象的析构函数是否被调用并正常工作,即它不会引发任何错误,也不会返回错误的退出代码。
我一直在编写单元测试,因为似乎单元测试在对象被删除之前就完成了。我没有设法在测试返回之前强制删除对象,并且我不能__del__
直接在我的测试中调用,原因有两个:
这不是我正在测试的
这实际上最终导致对象被销毁两次,在我的情况下,析构函数释放了一些内存,因此在调用两次时会产生分段错误。
为了说明这一点,我创建了一个玩具示例,其中有两个对象。第一个,MyWrongObject
,在析构函数中包含一个错误,第二个MyCorrectObject
是正确的。我已经为这些对象中的每一个编写了测试。一个应该成功,而另一个应该失败。
import unittest
import gc
class MyWrongObject(object):
def __init__(self):
self.del_calls = 0
def __del__(self):
if self.del_calls:
# Something really bad can happen here like a segmentation fault
# because we may free some memory twice
raise AssertionError("Already destroyed")
self.del_calls += 1
# Simulate an error
raise ValueError("Error while destroying the object")
class MyCorrectObject(object):
def __init__(self):
self.del_calls = 0
def __del__(self):
if self.del_calls:
# Something really bad can happen here like a segmentation fault
# because we may free some memory twice
raise AssertionError("Already destroyed")
self.del_calls += 1
# No error here
class TestDestructor(unittest.TestCase):
def test_my_correct_object_should_destroy_itself(self):
# Given
my_object = MyCorrectObject()
# When / Then
del my_object
gc.collect()
# This test should fail
def test_my_wrong_object_should_destroy_itself(self):
# Given
my_object = MyWrongObject()
# When / Then
del my_object
gc.collect()
在当前状态下,两个测试都成功了,第二个测试打印了ValueError
in stdout:
python -m unittest snips_nlu.tests.test_destructor.TestDestructor 1 ↵
.Exception ignored in: <bound method MyWrongObject.__del__ of <snips_nlu.tests.test_destructor.MyWrongObject object at 0x1118bbda0>>
Traceback (most recent call last):
File "/Users/adrien/dev/snips-nlu/snips_nlu/tests/test_destructor.py", line 17, in __del__
raise ValueError("Error while destroying the object")
ValueError: Error while destroying the object
.
----------------------------------------------------------------------
Ran 2 tests in 0.044s
OK
我无法以一致的方式编写这些测试(在两者中使用相同的代码),并且第一个通过而第二个失败(AssertionError
在标准输出中没有任何内容)。
谢谢你的帮助!