""" Unit Name: hs.testcase Created By: Virgil Dupras Created On: 2007/06/23 Last modified by:$Author: virgil $ Last modified on:$Date: 2008-02-18 22:11:43 +0100 (Mon, 18 Feb 2008) $ $Revision: 2396 $ Copyright 2007 Hardcoded Software (http://www.hardcoded.net) """ import unittest import gc import os.path as op import shutil import tempfile import threading from hs.path import Path class TestCase(unittest.TestCase): cls_tested_module = None def run(self, result=None): self._created_directories = [] self._mocked = [] unittest.TestCase.run(self, result) for thread in threading.enumerate(): if thread.getName() != 'MainThread' and thread.isAlive(): if hasattr(thread, 'close'): thread.close() thread.join(1) gc.collect() # Forces instances that hold file resources to be freed allowing tmpdir clearance to work. for path in self._created_directories: if op.exists(path): shutil.rmtree(path) # We use reversed() so the original value is put back, even if we mock twice. for target, attrname, old_value in reversed(self._mocked): setattr(target, attrname, old_value) def mock(self, target, attrname, replace_with): ''' Replaces 'target' attribute 'attrname' with 'replace_with' and put it back to normal at tearDown. The very nice thing about mock() is that it will scan self.cls_tested_module for the mock target and mock it as well. This is to fix the "from" imports problem (Where even if you mock(os, 'path'), if the tested module imported it with "from os import path", the mock will not work). ''' oldvalue = getattr(target, attrname) self._mocked.append((target, attrname, oldvalue)) setattr(target, attrname, replace_with) if (self.cls_tested_module is not None) and (self.cls_tested_module is not target): for key, value in self.cls_tested_module.__dict__.iteritems(): if value is oldvalue: self.mock(self.cls_tested_module, key, replace_with) def tmpdir(self, ref=None): ''' Creates a new temp directory for you to put stuff in. You don't have to worry about cleaning it up, it's automatically cleaned up on tearDown. ''' result = tempfile.mkdtemp() self._created_directories.append(result) if ref is not None: shutil.rmtree(result) shutil.copytree(ref,result) return result def tmppath(self, ref=None): return Path(self.tmpdir(ref)) def assertContentIsEqual(self, expected, actual): expected.sort() actual.sort() self.assertEqual(expected, actual) def assertContentIsNotEqual(self, expected, actual): self.assertRaises(AssertionError, self.assertContentIsEqual, expected, actual)