本文系《pytest源码剖析》系列内容
33. faulthandler
插件路径:_pytest.faulthandler
实现的 hook
调用的 hook
无
定义的 fixture
无
插件功能
创建 ini 配置项faulthandler_timeout
显示耗时用例的执行过程
代码片段
@pytest.hookimpl(hookwrapper=True, trylast=True)def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]: timeout = get_timeout_config_value(item.config) stderr = item.config.stash[fault_handler_stderr_key] if timeout > 0 and stderr is not None: import faulthandler
faulthandler.dump_traceback_later(timeout, file=stderr) try: yield finally: faulthandler.cancel_dump_traceback_later() else: yield
@pytest.hookimpl(tryfirst=True)def pytest_enter_pdb() -> None: """Cancel any traceback dumping due to timeout before entering pdb.""" import faulthandler
faulthandler.cancel_dump_traceback_later()
@pytest.hookimpl(tryfirst=True)def pytest_exception_interact() -> None: """Cancel any traceback dumping due to an interactive exception being raised.""" import faulthandler
faulthandler.cancel_dump_traceback_later()
在用例执行前,设置超时时间。超时自动 dump 跟踪栈
进入 pdb 调试模式时,取消超时设置
进入交互模式时,取消超时设置
简评
这是最后一个默认插件,
和前面的unraisableexception和threadexception一样,都是为了更好的使用 python 内置的功能
...
先看一个 pythonfaulthandler的用法
import faulthandlerimport time
faulthandler.dump_traceback_later(1) # 超过1秒的代码会被dump
def a(): time.sleep(1.5)
def b(): time.sleep(1.5)
def my_faulty(): a() b()
my_faulty()
执行结果
Timeout (0:00:01)!Thread 0x00005474 (most recent call first): File "E:\PyProject\pytest_7.2.x\aaa.py", line 8 in a File "E:\PyProject\pytest_7.2.x\aaa.py", line 16 in my_faulty File "E:\PyProject\pytest_7.2.x\aaa.py", line 20 in
由结果可见,faulthandler 可以显示 python 文件的调用关系
在本例中,以显示首个执行时间超过 1 秒的代码为目标,进行显示
...
本插件通首先获取 ini 配置faulthandler_timeout的值,如果大于 0,则在用例执行前调用
faulthandler.dump_traceback_later
这样,当用例执行超时时,会自动显示跟踪栈(但不会修改用例结果为失败)
领取专属 10元无门槛券
私享最新 技术干货