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
相关产品推荐
相关产品推荐

