更灵活方便的初始化、清除方法——fixture【pytest】

转载自白月黑羽,pytest 框架 - 白月黑羽,仅作学习笔记用途,侵权联系删除


pytest 中使用 fixture 的方法与机制详解

在前面介绍的 unittest 风格初始化与清除机制中,我们主要使用 setup_*teardown_* 方法对资源进行前后处理。而 pytest 提供了更加灵活、声明式 的替代方案 ------ fixture,使得测试代码更加模块化、可复用。


一、基本用法:声明式依赖注入

fixture 的最大优势之一是:测试函数通过参数声明所依赖的资源 ,pytest 会自动识别并注入。这种机制被称为 依赖注入(Dependency Injection)

示例:创建张三账号的 fixture
python 复制代码
import pytest

@pytest.fixture
def create_zhangsan():
    print('\n>>> 创建张三账号')
    return {
        'username': 'zhangsan',
        'password': '111111',
        'invitecode': 'abcdefg'
    }

def test_A001001(create_zhangsan):
    print('用例 A001001')
    print('邀请码是:', create_zhangsan['invitecode'])

def test_C001001():
    print('用例 C001001')

执行:

复制代码
python -m pytest -sv

输出效果

  • 只有 test_A001001 引用了 create_zhangsan,因此该 fixture 会在它执行前被自动调用;
  • test_C001001 没有声明依赖,不会触发任何 fixture

二、添加清除逻辑:使用 yield

如果 fixture 中需要在测试执行后清除数据或关闭资源,可以通过 yield 实现:

python 复制代码
@pytest.fixture
def create_zhangsan():
    print('\n>>> 初始化张三账号')
    user = {'username': 'zhangsan', 'password': '111111'}
    yield user
    print('\n>>> 清除张三账号')

yield 之前的代码是 初始化部分 ,之后是 清理操作 。pytest 会自动在测试函数执行完成后调用 yield 后的清除逻辑。


三、支持参数化的 fixture(带参数)

通过 @pytest.mark.parametrizeindirect=True 配合,可以将参数传递给 fixture 函数,从而实现动态用户生成

python 复制代码
@pytest.fixture
def create_user(request):
    print('\n>>> 创建用户')
    return {
        'username': request.param[0],
        'password': request.param[1],
        'invitecode': 'abcdefg'
    }

@pytest.mark.parametrize("create_user", [("zhangsan", "111")], indirect=True)
def test_login_zhangsan(create_user):
    print('用户名:', create_user['username'])

@pytest.mark.parametrize("create_user", [("lisi", "222")], indirect=True)
def test_login_lisi(create_user):
    print('用户名:', create_user['username'])

request 是 pytest 提供的特殊对象,可以访问传入的参数值。


四、fixture 的作用域(scope)

通过设置 scope 参数,可以控制 fixture 的生命周期:

|------------|---------|-------------------------|
| scope 值 | 含义 | 生命周期控制方式 |
| function | 默认作用域 | 每个测试函数/方法都会调用一次 |
| class | 类级别 | 每个类开始前初始化,类结束后清除 |
| module | 模块级别 | 每个模块文件开始前初始化,模块执行完后清除 |
| package | 目录(包)级别 | 针对目录下所有模块,仅初始化一次 |
| session | 会话级别 | 整个 pytest 执行期间仅初始化与清除一次 |

示例:函数级别(默认)
python 复制代码
@pytest.fixture(scope='function')
def user_env():
    print('\n>>> 准备环境')
    yield
    print('\n>>> 清除环境')

如果该 fixture 被多个测试函数使用,每次都会初始化和清理一次。

示例:类级别
python 复制代码
@pytest.fixture(scope='class')
def db_conn():
    print('\n>>> 打开数据库连接')
    yield
    print('\n>>> 关闭数据库连接')

在整个类内仅初始化/清理一次,非常适合数据库连接、登录状态等共享资源。


五、自动调用 fixture(autouse=True

在默认行为中,fixture 只有被测试函数显式声明时才会生效。如果想要全局自动使用 某个 fixture,可以设置 autouse=True

python 复制代码
@pytest.fixture(scope='module', autouse=True)
def setup_env():
    print('\n>>> 自动初始化数据环境')
    yield
    print('\n>>> 自动清除数据环境')

此时,无需在测试函数中写参数声明,pytest 会自动执行该 fixture。


六、conftest.py 文件:项目级 fixture 管理

如果你希望 fixture 被多个模块或目录共享,而又不希望每次都 import,可以将其放入同级目录下的 conftest.py 文件中。

python 复制代码
# conftest.py
import pytest

@pytest.fixture(scope='package', autouse=True)
def env_setup():
    print('\n>>> 目录初始化')
    yield
    print('\n>>> 目录清除')
  • 不需要 import,pytest 会自动识别 conftest.py 中的内容;
  • 多个目录下可分别放置 conftest.py 以实现本地初始化与隔离清理;
  • 可以避免不同测试之间产生环境污染。

七、整体测试级别(session)清理资源

有些资源(如数据库连接池、临时测试服务器)只希望在整个 pytest 运行过程中初始化一次,并在结束时清理,此时使用:

python 复制代码
@pytest.fixture(scope='session', autouse=True)
def global_init():
    print('\n>>> 全局环境初始化')
    yield
    print('\n>>> 全局环境清理')

小结

|-----------------|-----------------------------------------------------|
| 特性 | 描述 |
| 声明式使用 | 测试函数通过参数声明所需 fixture,pytest 自动识别 |
| 支持资源清理 | 使用 yield 插入清除逻辑 |
| 参数化 fixture | 结合 @pytest.mark.parametrize(indirect=True) 实现灵活输入 |
| 作用域控制 | 支持函数、类、模块、目录、会话多级别控制 |
| 自动执行 | autouse=True 无需显式声明即可触发 |
| 集中式定义 | 使用 conftest.py 统一配置,提高复用性与清晰度 |

相关推荐
Scott9999HH4 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
AI云海5 小时前
python 列表、元组、集合和字典
开发语言·python
二十雨辰5 小时前
[爬虫]-Urllib
爬虫·python
玉鸯7 小时前
Agent Hook:在概率推理之上,为 Agent 叠加确定性控制
python·langchain·agent
weixin_446260858 小时前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
我的xiaodoujiao8 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
吳所畏惧8 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh
DFT计算杂谈8 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
qetfw8 小时前
MXU:Tauri 2 + React 的 MaaFramework 跨平台 GUI 源码
前端·python·react.js·前端框架·开源项目·效率工具