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

session级pytest fixture重复实例化问题及实现方案咨询

解决pytest session级fixture重复创建的问题

问题描述

需要实现一个session级的pytest fixture,要求在测试会话启动时创建,供所有测试文件及模块的测试用例复用,会话结束时销毁(比如单次运行的串口连接)。但设置scope='session'后,每个测试文件都会创建一个my_fixture实例,而非仅创建一次。

目录结构

/test/fixture_1.py
/test/test_1.py
/test/test_2.py
/pytest.ini

执行计划异常输出

(venv) PS C:\tmp_test_pytest> pytest -m single_source  -s --setup-plan                              
============================ test session starts ================================
platform win32 -- Python 3.10.4, pytest-7.4.3, pluggy-1.3.0
rootdir: C:\tmp_test_pytest
configfile: pytest.ini
collected 3 items           

test\test_1.py
SETUP    S my_fixture
        test/test_1.py::test_from_other_file_src1 (fixtures used: my_fixture)
test\test_2.py
SETUP    S my_fixture
        test/test_2.py::test_from_other_file_src21 (fixtures used: my_fixture)
        test/test_2.py::test_from_other_file_src22 (fixtures used: my_fixture)
TEARDOWN S my_fixture
TEARDOWN S my_fixture

原有代码

  • /test/fixture_1.py:
import pytest
import datetime
import time
import sys

@pytest.fixture(scope="session")
def my_fixture():
    stamp = datetime.datetime.now().strftime("%H:%M:%S.%f")
    time.sleep(5)
    print("huhu", file=sys.stderr)
    return stamp
  • 测试文件/test/test_1.py:
from test.fixture_1 import my_fixture
@pytest.mark.single_source
def test_from_other_file_src1(my_fixture):
    print(f"test_from_other_file: {my_fixture}", file=sys.stderr)
  • 测试文件/test/test_2.py:
from test.fixture_1 import my_fixture
@pytest.mark.single_source
def test_from_other_file_src21(my_fixture):
    print(f"test_from_other_file: {my_fixture}", file=sys.stderr)

@pytest.mark.single_source
def test_from_other_file_src22(my_fixture):
    print(f"test_from_other_file: {my_fixture}", file=sys.stderr)
  • /pytest.ini:
[pytest]
markers =
    single_source: single source, same import path

解决方案

核心原因

手动在每个测试文件中import fixture时,pytest会将每个导入的fixture视为独立定义(即使代码完全一致),因为导入上下文不同,导致session级fixture被重复初始化。

修复步骤

  1. 将fixture移至conftest.py
    pytest会自动加载测试目录下的conftest.py,其中的fixture会被全局注册,无需手动import。创建/test/conftest.py并写入fixture代码:
import pytest
import datetime
import time
import sys

@pytest.fixture(scope="session")
def my_fixture():
    stamp = datetime.datetime.now().strftime("%H:%M:%S.%f")
    time.sleep(5)
    print("huhu", file=sys.stderr)
    return stamp

之后可以删除原有的/test/fixture_1.py。

  1. 修改测试文件,移除手动import
    测试文件中直接在测试函数参数里使用my_fixture即可,无需导入:
    /test/test_1.py:
import pytest

@pytest.mark.single_source
def test_from_other_file_src1(my_fixture):
    print(f"test_from_other_file: {my_fixture}", file=sys.stderr)

/test/test_2.py:

import pytest

@pytest.mark.single_source
def test_from_other_file_src21(my_fixture):
    print(f"test_from_other_file: {my_fixture}", file=sys.stderr)

@pytest.mark.single_source
def test_from_other_file_src22(my_fixture):
    print(f"test_from_other_file: {my_fixture}", file=sys.stderr)
  1. 验证修复效果
    重新执行命令:
pytest -m single_source -s --setup-plan

输出会显示仅一次SETUP和TEARDOWN:

============================ test session starts ================================
platform win32 -- Python 3.10.4, pytest-7.4.3, pluggy-1.3.0
rootdir: C:\tmp_test_pytest
configfile: pytest.ini
collected 3 items           

SETUP    S my_fixture
test\test_1.py
        test/test_1.py::test_from_other_file_src1 (fixtures used: my_fixture)
test\test_2.py
        test/test_2.py::test_from_other_file_src21 (fixtures used: my_fixture)
        test/test_2.py::test_from_other_file_src22 (fixtures used: my_fixture)
TEARDOWN S my_fixture

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:06:03