Daily Technical Tracking

每周科技追踪 · 10月第3周

2026年10月第3周 · 技术 / 产品 / 公司

每日追踪
← 返回首页

pytest 开并发,用例被报两次

用 pytest_report_teststatus 钩子收集用例结果并上报,本地跑一切正常;一旦给命令加上 -n,同一个用例就上报两次。规律很固定:-n 1 是两次,-n 5 也是两次,恰好翻倍,而 pytest 输出里每个用例只出现一次 PASSED。重复发生在「上报」这一环,不在执行这一环。

根因在 pytest-xdist 的进程模型。-n 会启动 master 加 N 个 worker,不带 -n 时只有一个进程;-n 1 也不是单进程,而是 master 加 gw0 两个。pytest_report_teststatus 在两侧各被调用一次:worker 自己执行用例时触发一次,master 汇总各 worker 回传的结果时再触发一次。所以只要开了 -n,哪怕只有 1 个 worker,也会翻倍。

为什么 -n 5 不是 6 次?默认调度下每个用例只分配给一个 worker 执行,worker 侧对单个用例只报一次,master 汇总侧再报一次,上报次数恒等于 2,与 worker 数量无关。在 pytest_collection_finish 里判断过并发模式也不够——那个钩子只管用例清单上传,与结果上报是两段逻辑,需要各自加判断。

推荐做法是拿 report.worker_id 当判别依据:这个属性由 xdist 注入,只在并发模式下存在,用 hasattr(report, 'worker_id') 判断,本地单进程直接 return,流水线里才走上报。流水线可把 PYTEST_CONCURRENCY 默认设为 -n 1 并允许覆盖,这样本地调试不会产生脏数据。客户端过滤只能做到「少发」,网络重试、重复启动、rerun 插件仍会造成重复,服务端还要用 pipeline_id 加 task_id 加 node_id 加执行序号做唯一键幂等,两层一起才稳。