While running unit tests (most of them integration tests) with Python I create some directories. They need to be deleted after the test or when the test fails. The execution of the cleanup code need to be guaranteed.
- A fake or virtual filesystem (e.g.
pyfakefs
) or isn't a solution my situation because my unit tests call external tools (e.g.rsync
) viasubprocess.Popen
. Also separatedramfs
based filesystems not an option. - I prefer vanilla
unittest
instead ofpytest
. - The directories need to have a specific name. Random names are a problem.
My current solution is a class that holds a pathlib.Path
instance as a member and deletes it from the filesystem in its __del__()
method.
#!/usr/bin/env python3
import unittest
import pathlib
import shutil
import time
class SelfDestructingPath:
def __init__(self, path):
print('init')
self._path = pathlib.Path(path)
self._path.mkdir()
def __del__(self):
shutil.rmtree(self._path)
print('del')
@property
def path(self):
return self._path
class MyTest(unittest.TestCase):
def test_foobar(self):
print('test start')
sdp = SelfDestructingPath('auto_delete')
self.assertTrue(sdp.path.exists())
time.sleep(5)
self.assertTrue(False)
print('test end')
if __name__ == '__main__':
unittest.main()
The question here is if there is a more elegant solution.
I know about context managers. But in my case I don't see an advantage to them. My solution does save me one indention because I don't have to create a with
block. In my application I use that feature heavily.
Another alternative would be to derive from pathlib.Path
: class SelfDestructingPath(pathlib.Path)
. But I read somewhere that it is often not a good choice to derive from Python's own packages when you don't know what you are doing.
Any suggestions to improve this or to make it more pythonic?
pyfakefs
and Co (which use ramfs) not an option for my integration tests. \$\endgroup\$rsync
will happily treat a ramfs the same way. \$\endgroup\$