我有一个函数来捕获未捕获的异常,如下所示。有没有办法编写一个单元测试来执行uncaught_exception_handler()
函数,但正常退出测试?
import logging
def config_logger():
# logger setup here
def init_uncaught_exception_logger(logger):
'''Setup an exception handler to log uncaught exceptions.
This is typically called once per main executable.
This function only exists to provide a logger context to the nested function.
Args:
logger (Logger): The logger object to log uncaught exceptions with.
'''
def uncaught_exception_handler(*exc_args):
'''Log uncaught exceptions with logger.
Args:
exc_args: exception type, value, and traceback
'''
print("Triggered uncaught_exception_handler")
logger.error("uncaught: {}: {}n{}".format(*exc_args))
sys.excepthook = uncaught_exception_handler
if __name__ == '__main__':
LOGGER = config_logger()
init_uncaught_exception_logger(LOGGER)
raise Exception("This is an intentional uncaught exception")
与其测试是否为未捕获的异常调用函数,不如测试是否安装了excepthook
,以及手动调用函数时该函数是否做了正确的事情。这为excepthook
在实际使用中的表现提供了很好的证据。您需要将uncaught_exception_handler
移到init_uncaught_exception_logger
之外,以便您的测试可以更轻松地访问它。
assert sys.excepthook is uncaught_exception_handler
with your_preferred_output_capture_mechanism:
try:
1/0
except ZeroDivisionError:
uncaught_exception_handler(*sys.exc_info())
assert_something_about_captured_output()
如果您想通过未捕获的异常实际调用excepthook
,那么您需要启动一个子流程并检查其输出。subprocess
模块就是实现这一目标的途径。
为了编写关于引发异常的断言,可以使用pytest.raises
作为上下文管理器,如下所示:
带提升(expected_exception:exception[,match][,message](
import pytest
def test_which_will_raise_exception():
with pytest.raises(Exception):
# Your function to test.
现在,只有当pytest.raises上下文管理器下的任何代码将引发作为参数提供的异常时,此单元测试才会通过。在这种情况下,它是Exception
。