"""Pytest plugin to capture unhandled exception""" from __future__ import print_function try: from cStringIO import StringIO except ImportError: try: from StringIO import StringIO except ImportError: from io import StringIO import sys import traceback import pytest class CaptureExcPlugin(object): """Capture unhandled exception (probably raised inside event loop)""" def pytest_addoption(self, parser): parser.addoption('--no-capture-exc', dest='capture_exc', action='store_false', default=True, help='Catch unhandled exception to report as error') def pytest_configure(self, config): options = config.known_args_namespace self.enabled = options.capture_exc @pytest.mark.hookwrapper def pytest_runtest_call(self, item): self._origexcepthook = sys.excepthook sys.excepthook = self._excepthook self._excepts = [] try: yield finally: sys.excepthook = self._origexcepthook del self._origexcepthook if self._excepts: out = StringIO() print("%s uncaught exception(s):" % len(self._excepts), file=out) for exc_info in self._excepts: print(file=out) traceback.print_exception(*exc_info, file=out) del self._excepts[:] pytest.fail(out.getvalue(), pytrace=False) def _excepthook(self, type, value, traceback): self._excepts.append((type, value, traceback))