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

pytest6.2.5运行报错Session对象无results属性是什么原因

问题原因
  • 最常见诱因是启用了pytest-xdist分布式执行插件:xdist会启动多个独立的worker进程,每个进程持有独立的Session实例。你在主进程pytest_sessionstart钩子中为Session添加的results属性无法同步到worker进程,worker执行测试时访问item.session.results就会触发属性不存在的报错。
  • conftest.py加载范围异常:如果你的conftest.py没有放在pytest执行命令的根目录,或者测试用例的顶层目录下,pytest_sessionstart钩子不会被pytest加载执行,自然不会初始化Session的results属性。
  • 第三方插件抢占hook执行:如果有其他插件也实现了pytest_sessionstart钩子且优先级更高,可能导致你的钩子逻辑被覆盖、执行中断,results属性没有被初始化。
解决方案

方案1:验证基础配置

先在你的pytest_sessionstart函数中添加打印日志,运行pytest时检查是否有对应的输出:

  • 没有输出:说明钩子未被加载,将conftest.py移动到pytest执行命令的根目录下即可。
  • 有输出:说明是xdist或者属性冲突导致的问题,继续看下面的方案。

方案2:兼容所有场景的代码修改

使用pytest 6.2+内置的stash存储全局数据,避免直接给Session对象动态加属性导致的冲突,修改后的conftest.py代码如下:

import pytest

# 定义唯一的stash键,避免和其他插件的存储冲突
RESULTS_STASH_KEY = pytest.StashKey[dict]()

def pytest_sessionstart(session):
    print("session start")
    session.stash[RESULTS_STASH_KEY] = dict()

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    result = outcome.get_result()
    if result.when == "call":
        item.session.stash[RESULTS_STASH_KEY][item] = result

@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    print()
    print("run status code:", exitstatus)
    results = session.stash[RESULTS_STASH_KEY]
    passed_amount = sum(1 for res in results.values() if res.passed)
    failed_amount = sum(1 for res in results.values() if res.failed)
    print(f"passed: {passed_amount}, failed: {failed_amount}")

方案3:如果你使用了pytest-xdist

如果需要保留分布式执行能力,除了上面的代码修改,还需要额外实现xdist的结果同步逻辑,在conftest.py中新增以下钩子即可:

def pytest_configure(config):
    # 适配xdist,worker进程不需要处理最终汇总
    if hasattr(config, "workerinput"):
        @pytest.hookimpl(tryfirst=True)
        def pytest_sessionfinish(session, exitstatus):
            # 将worker的结果回传给主进程
            config.workeroutput["results"] = session.stash[RESULTS_STASH_KEY]

def pytest_sessionfinish(session, exitstatus):
    if not hasattr(session.config, "workerinput"):
        # 主进程汇总所有worker的结果
        if hasattr(session.config, "workeroutput"):
            all_results = {}
            for worker_out in session.config.workeroutput.values():
                all_results.update(worker_out.get("results", {}))
            session.stash[RESULTS_STASH_KEY] = all_results
        # 后续执行你的自定义逻辑即可
        results = session.stash[RESULTS_STASH_KEY]
        passed_amount = sum(1 for res in results.values() if res.passed)
        failed_amount = sum(1 for res in results.values() if res.failed)
        print(f"total passed: {passed_amount}, total failed: {failed_amount}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:27:05