如何识别pytest-xdist工作进程上正在运行的测试用例
pytest-forked 并行执行时实时定位进程对应测试用例方案
核心实现原理
Linux系统下进程可自行修改自身的进程名(/proc/<pid>/comm)与命令行参数(/proc/<pid>/cmdline)字段,修改后可直接通过ps、top等系统工具读取,无需依赖第三方监控组件。
结合pytest的用例执行钩子,在每个用例启动时将用例标识写入当前执行进程的对应字段,即可实时查询每个worker进程正在运行的测试用例,精准定位拖尾的单测。
具体操作步骤
- 将以下代码写入测试根目录的
conftest.py文件,pytest会自动加载该钩子逻辑,无需修改原有测试执行命令:
import ctypes import pytest libc = ctypes.CDLL("libc.so.6") PR_SET_NAME = 15 def set_current_proc_name(name: str): # comm字段最长支持15字节,超长自动截断 proc_name = name[:15].encode("utf-8") libc.prctl(PR_SET_NAME, proc_name, 0, 0, 0) @pytest.hookimpl(hookwrapper=True) def pytest_runtest_setup(item): # 用例启动前将进程名设置为pytest:前缀+用例唯一标识 set_current_proc_name(f"pytest:{item.nodeid}") yield @pytest.hookimpl(hookwrapper=True) def pytest_runtest_teardown(item): yield # 用例执行完成后重置进程为空闲状态 set_current_proc_name("pytest:idle")
如果需要查看完整无截断的用例名称,可替换
set_current_proc_name实现为修改cmdline的版本,执行ps时args列会输出完整用例路径与名称:def set_current_proc_name(name: str): with open("/proc/self/cmdline", "wb") as f: f.write(f"[pytest running] {name}".encode("utf-8") + b"\0")
- 正常启动测试,当观察到机器CPU使用率明显下降、大部分worker进程无占用时,执行以下命令查询所有pytest相关进程的运行状态:
ps -eo pid,pcpu,comm,args | grep pytest
输出结果中,非pytest:idle状态的进程对应的用例名,就是当前仍在执行的用例;当仅剩1个进程处于运行状态、其余全部为idle时,该进程显示的用例就是导致队列拖尾的目标用例。
兼容性说明
该方案完全兼容pytest-forked与pytest-xdist的并行模式:由于pytest-forked会为每个测试用例fork独立执行进程,钩子逻辑会在每个独立进程内触发修改自身进程名,不会出现多用例进程名串扰的问题。
注:pytest --durations=0参数可输出所有用例的执行耗时,但该方式仅能统计用例自身执行时长,无法识别因任务调度顺序导致的拖尾问题,实时进程查询的方式不存在该缺陷。
内容的提问来源于stack exchange,提问作者orange
相关产品推荐
相关产品推荐

