title: How to test that a custom excepthook is installed correctly?
body: <p>My app logs unhandled exceptions.  </p>
  
  <pre><code># app.py
  import logging
  import sys
  
  logger = logging.getLogger(__name__)
  
  def excepthook(exc_type, exc_value, traceback):
      exc_info = exc_type, exc_value, traceback
      if not issubclass(exc_type, (KeyboardInterrupt, SystemExit)):
          logger.error('Unhandled exception', exc_info=exc_info)
      sys.__excepthook__(*exc_info)
  
  sys.excepthook = excepthook
  
  def potato():
      logger.warning('about to die...')
      errorerrorerror
  
  if __name__ == '__main__':
      potato()
  </code></pre>
  
  <p>These tests pass OK:</p>
  
  <pre><code># test_app.py
  import app
  import pytest
  import sys
  from logging import WARNING, ERROR
  
  def test_potato_raises():
      with pytest.raises(NameError):
          app.potato()
  
  def test_excepthook_is_set():
      assert sys.excepthook is app.excepthook
  
  # for caplog plugin: pip install pytest-catchlog
  def test_excepthook_logs(caplog):  
      try:
          whatever
      except NameError as err:
          exc_info = type(err), err, err.__traceback__
      app.excepthook(*exc_info)
      assert caplog.record_tuples == [('app', ERROR, 'Unhandled exception')]
      [record] = caplog.records
      assert record.exc_info == exc_info
  </code></pre>
  
  <p>But I couldn't get a test of unhandled exceptions logging working:</p>
  
  <pre><code>def test_unhandled_exceptions_logged(caplog):
      try:
          app.potato()
      finally:
          assert caplog.record_tuples == [
              ('app', WARNING, 'about to die...'),
              ('app', ERROR, 'Unhandled exception'),
          ]
          return  # return eats exception
  </code></pre>
  
  <p>What's wrong here?  How can we actually trigger the <code>app.excepthook</code> from within a test?</p>