You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pytest-xdist下pytest_session钩子多次触发引发测试失败问题

使用pytest-xdist时控制session级钩子仅执行一次

我在用pytest结合pytest-xdist编写测试,想要实现所有worker启动前仅执行一次pytest_sessionstart,所有worker完成后仅执行一次pytest_sessionfinish。

但当前方案未达预期:测试运行期间会触发多次session的启动与结束,导致清理操作重复执行,直接清理了临时目录,测试因FileNotFoundError失败。添加日志后发现,所有worker启动后、结束前仍有session启动并触发清理。

现有代码如下:

def pytest_sessionstart(session: pytest.Session):
    if hasattr(session.config, 'workerinput'):
        # log to file 'worker init {id}'
        return
    # log to file 'init {sess id}'
    # do some stuff

def pytest_sessionfinish(session: pytest.Session, exitstatus: int):
    if hasattr(session.config, 'workerinput'):
        # log to file 'worker done {id}'
        return
    # log to file 'cleanup {sess id} {exitstatus}'
    # do some stuff

解决方案

核心是区分主进程的根session与其他子session(如插件或子进程触发的session),通过以下两种方式实现:

方式一:检查session父节点与worker属性

def pytest_sessionstart(session: pytest.Session):
    # 跳过worker进程与子session的初始化
    if hasattr(session.config, 'workerinput') or session.parent is not None:
        # log to file 'worker init {id}'
        return
    # 执行主进程初始化操作
    # log to file 'init {sess id}'
    # do some stuff

def pytest_sessionfinish(session: pytest.Session, exitstatus: int):
    # 跳过worker进程与子session的清理
    if hasattr(session.config, 'workerinput') or session.parent is not None:
        # log to file 'worker done {id}'
        return
    # 执行主进程清理操作
    # log to file 'cleanup {sess id} {exitstatus}'
    # do some stuff

方式二:使用xdist专属标记is_xdist_master

def pytest_sessionstart(session: pytest.Session):
    # 仅在xdist主进程的根session执行初始化
    if not getattr(session.config, 'is_xdist_master', False) or session.parent is not None:
        return
    # log to file 'init {sess id}'
    # do some stuff

def pytest_sessionfinish(session: pytest.Session, exitstatus: int):
    # 仅在xdist主进程的根session执行清理
    if not getattr(session.config, 'is_xdist_master', False) or session.parent is not None:
        return
    # log to file 'cleanup {sess id} {exitstatus}'
    # do some stuff

说明

  • session.parent is not None:用来排除子session(比如参数化、插件生成的嵌套session),避免这些场景误触发初始化/清理
  • is_xdist_master:xdist为父进程添加的专属标记,比判断workerinput更直接精准,能明确识别是否是xdist的主控制进程

通过以上修改,可确保初始化操作仅在所有worker启动前执行一次,清理操作仅在所有worker完成后执行一次,不会因中间的子session触发重复操作。

内容的提问来源于stack exchange,提问作者maciek97x

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:01:56