I want to test that the destructor of a Python object is called and works properly, i.e. it doesn't raise any error nor returns a bad exit code.
I am stuck in writing the unit test, because it seems that the unit test finishes before the object is deleted. I did not manage to force the object to be deleted before the test returns, and I can't afford to call __del__ directly in my tests for two reasons:
-
That's not exactly what I'm testing
-
This actually ends up in the object being destroyed twice, and in my case the destructor frees some memory so it creates a segmentation fault when called twice.
To illustrate this, I've created a toy example where I have two objects. The first one, MyWrongObject, contains a bug in the destructor and the second one MyCorrectObject is correct. I've written tests for each of these objects. One should succeed while the other should fail.
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()
del my_object
gc.collect()
# This test should fail
def test_my_wrong_object_should_destroy_itself(self):
# Given
my_object = MyWrongObject()
del my_object
gc.collect()
In the current state, both tests succeed, with the second one prints the 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
I can't manage to write these tests in a consistent way (using the same code in both), and have the first one pass while the second one fails (without any AssertionError in the stdout).
Thanks for your help!
Aucun commentaire:
Enregistrer un commentaire