I don’t know if using many threads for testing is a good practice or not. However, I do use it, and I do suffer the consequences from it.
Python’s Unittest library will not heed whatever exception thrown from other threads than the main thread it running on!
This will definitely cause problems especially when exceptions happen and your tests are still quite green, that cannot be good.
One way to mitigate this problem is to create a GlobalExceptionWatcher that will see any exception thrown from any thread.
The implementation I found over the internet was kinda hack, yet using with cautions it worked!
class GlobalExceptionWatcher(object): import threading import os ''' NOTE: It changes the behavior of 'threading' module, which should be use in only limited area on a limited run ''' def _store_excepthook(self): ''' Uses as an exception handlers which stores any uncaught exceptions. ''' formated_exc = self.__org_hook() self._exceptions.append(formated_exc) return formated_exc def start(self): ''' Register us to the hook. ''' self._exceptions =  self.__org_hook = self.threading._format_exc self.threading._format_exc = self._store_excepthook def stop(self): ''' Remove us from the hook, assure no exception were thrown. ''' self.threading._format_exc = self.__org_hook if len(self._exceptions) != 0: tracebacks = self.os.linesep.join(self._exceptions) raise Exception('Exceptions in other threads: %s' % tracebacks) def __enter__(self): self.start() def __exit__(self, type, value, traceback): self.stop()
You can now use:
class ExceptionOnThreadTest(unittest.TestCase): def test_exception_on_thread(self): import threading def run(): import time time.sleep(0.1) raise Exception('just an exception') def watcher(): with GlobalExceptionWatcher(): t = threading.Thread(target=run) t.start() t.join() self.assertRaises(Exception, watcher)
And it turned red beautifully…