7. Fixture :自动化前后置

承接前文 Pytest 用例规则、前后置 setup、断言、参数化,本篇详解Fixture 。Fixture 是 Pytest 框架最核心特色,完美解决原生setup_method/setup_class局限性,实现前后置复用、依赖注入、全局环境管理,是接口 / UI 自动化框架搭建必备。

一、Fixture 是什么?对比原生 setup 的优势

1. 概念

@pytest.fixture装饰器定义资源 / 前置后置函数,以参数注入方式被用例调用 ,自动完成环境初始化、数据准备、资源销毁,替代老旧setup/teardown

2. setup 痛点 & Fixture 优势

原生 setup/teardown 缺点 Fixture 对应优势
绑定测试类,跨类 / 跨文件无法复用 可全局定义,整个项目任意用例引用
执行粒度固定:类 / 方法两级 scope 四种作用域(function/class/module/session)灵活控制生命周期
只能顺序执行,不能互相依赖 支持 Fixture 嵌套依赖、多层调用
无法实现用例参数化前置 自带 params 参数化,实现前置数据批量驱动
前后置写死在同一个方法 yield 分割前置 / 后置,代码分离可读性强

企业选型结论:新项目全部用 Fixture 替代 setup,仅老旧 unittest 项目兼容保留 setup 写法。

二、Fixture 基础入门:参数注入调用

1. 基础语法:定义 & 调用规则

@pytest.fixture修饰的函数,函数名直接作为测试用例形参,pytest 自动优先执行 fixture,再跑用例

python 复制代码
import pytest
# 定义fixture
@pytest.fixture
def login():
    print("【fixture】执行登录,获取token")
    return "token_123456"

# 用例通过形参传入login,自动触发执行
def test_list_page(login):
    print("访问列表页,携带{}请求".format(login))

def test_detail_page(login):
    print("访问详情页,携带{}请求".format(login))

执行结果:每条用例运行前自动执行 login 登录,实现登录逻辑复用,不用每个用例重复写登录代码。

复制代码
【fixture】执行登录,获取token
访问列表页,携带token_123456请求
【fixture】执行登录,获取token
访问详情页,携带token_123456请求

2. fixture 嵌套依赖(链式调用)

fixture 可依赖其他 fixture,pytest 自动按依赖顺序逐层执行,适合分层初始化:比如先创建订单→再创建订单商品。

python 复制代码
@pytest.fixture
def entry():
    return ["a"]

# 依赖entry fixture
@pytest.fixture
def order(entry):
    entry.append("b")
    return entry

# 用例只需要传入最外层order,自动先执行entry再执行order
def test_order_operate(order):
    assert order == ["a","b"]

3. 一个用例传入多个 fixture

用例形参可一次性接收多个 fixture,多个前置资源并行加载:

python 复制代码
@pytest.fixture
def fruit_apple():
    return "apple"
@pytest.fixture
def fruit_banana():
    return "banana"
# 同时接收两个fixture
def test_fruit_basket(fruit_apple,fruit_banana):
    basket = [fruit_apple,fruit_banana]
    assert len(basket) ==2

三、yield 实现前后置分离(Fixture 精髓)

return只能返回数据无法做后置,yield 关键字拆分前后置:yield 之前 = 用例执行前 (前置),yield 之后 = 用例跑完后 (后置),完美实现资源创建 + 销毁闭环(打开 / 关闭文件、连接 / 断开数据库)。

示例 1:通用初始化 & 清理模板

python 复制代码
@pytest.fixture
def open_close():
    # ==========前置:用例执行前
    print("前置:初始化连接资源")
    yield "资源对象" # 返回值传给用例
    # ==========后置:用例执行完毕
    print("后置:销毁、关闭资源")

def test_demo(open_close):
    print("执行测试用例,使用{}".format(open_close))

运行输出:

python 复制代码
前置:初始化连接资源
执行测试用例,使用资源对象
后置:销毁、关闭资源

示例 2:文件读写实战(创建文件→读写→自动关闭)

python 复制代码
@pytest.fixture
def file_handle():
    # 前置:打开文件
    f = open("test.txt","w+",encoding="utf-8")
    yield f
    # 后置:自动关闭文件,避免资源泄漏
    f.close()
    print("文件已关闭")

def test_file_opt(file_handle):
    file_handle.write("测试数据")
    file_handle.seek(0)
    content = file_handle.read()
    assert content == "测试数据"

四、scope 作用域:控制 Fixture 生命周期(4 种粒度)

@pytest.fixture(scope="粒度"),控制 fixture 多久创建销毁,从细到粗 4 个取值:

scope 取值 生效范围 执行规则 适用场景
function (默认) 单个测试用例 每条用例执行前后各运行 1 次 单用例独立临时数据、单次接口临时账号
class 测试类 一个测试类所有用例共用 1 次,类开头创建,类全部跑完销毁 一个模块下多个接口共用登录 token
module 单个 py 文件 当前整个.py 脚本所有用例只初始化 1 次 单个模块全局数据库连接
session 整个测试会话 项目全部用例只执行 1 次(全局) 整个自动化项目全局登录、环境初始化

示例:scope=class 类级别复用

python 复制代码
@pytest.fixture(scope="class")
def class_login():
    print("【类前置:仅执行1次】登录")
    yield
    print("【类后置:类结束销毁】退出登录")

class TestApi:
    def test_case1(self,class_login):
        print("用例1执行")
    def test_case2(self,class_login):
        print("用例2执行")

运行:整个类只登录 1 次,两个用例共用登录态,类跑完才退出登录。

session/module 一般配合conftest.py全局文件使用,实现跨文件全局前置。

五、autouse 自动执行:无需传参,全局自动生效

autouse=True:不用在用例形参填写 fixture 名称,满足 scope 范围的所有用例自动执行该 fixture,适合全局统一配置(全项目统一初始化日志、全局环境变量)。

python 复制代码
# 当前类下所有用例自动执行,不用手动传参
@pytest.fixture(scope="class",autouse=True)
def auto_setup():
    print("自动执行类前置")
    yield
    print("自动执行类后置")

class TestDemo:
    def test_a(self):
        pass
    def test_b(self):
        pass

六、params 参数化 Fixture:前置数据源批量驱动

fixture 内置params=数据集,实现 fixture 自身参数化,每组数据生成一条用例

侧重前置环境多组数据初始化,区别于@pytest.mark.parametrize用例参数化(侧重接口入参)。

python 复制代码
# params提供多组数据,自动循环生成多条用例
@pytest.fixture(params=["admin","user1","user2"])
def init_user(request):
    # request.param获取当前遍历参数
    print(f"创建用户:{request.param}")
    return request.param

# 不用额外参数化,自动3条用例
def test_user_login(init_user):
    print(f"用户{init_user}登录测试")

区别对比:

七、conftest.py 全局配置文件(项目级 fixture)

1. 规则

  1. 文件名固定 conftest.py 不可修改,放在项目目录;
  2. 同目录 + 子目录所有 py 脚本不用 import 导入,直接调用文件内 fixture
  3. 一般存放scope=module/session全局 fixture(全局登录、全局数据库连接),实现跨文件前后置复用。

项目目录结构

复制代码
项目根目录
├─ conftest.py    # 全局fixture
├─ test_case1/
│   └─ test_api1.py
└─ test_case2/
    └─ test_api2.py

conftest.py 代码:

python 复制代码
@pytest.fixture(scope="session")
def global_env():
    print("【全局session】整个项目只初始化一次环境")
    yield
    print("【全局销毁】项目所有用例跑完清理环境")

test_api1.py 直接使用:

python 复制代码
def test_demo(global_env):
    pass

八、Fixture 和 parametrize 参数化选型区别

  1. @pytest.mark.parametrize用例入参参数化,侧重接口请求参数、业务入参变化;
  2. fixture(params)前置资源参数化,侧重测试环境、前置准备数据变化(不同测试账号、不同测试环境)。

九、接口自动化综合实战(整合前文:前后置 + fixture + 断言)

python 复制代码
import pytest,requests
# 全局登录fixture
@pytest.fixture(scope="module")
def get_token():
    # 前置:登录接口拿token
    login_url = "https://jsonplaceholder.typicode.com/users/1"
    res = requests.get(login_url)
    token = f"token_{res.json()['id']}"
    yield token
    # 后置:登出
    print("登出账号,销毁token")

# 业务接口用例
def test_query_info(get_token):
    headers = {"token":get_token}
    res = requests.get("https://jsonplaceholder.typicode.com/posts/1",headers=headers)
    # 断言
    assert res.status_code ==200,"接口请求失败"
    assert res.json()["userId"] ==1

十、高频踩坑总结

  1. yield 前后代码严格分开:yield 前前置、yield 后后置,异常时 yield 之后代码依然会执行;
  2. conftest 就近原则:子目录 conftest 优先级高于根目录,就近调用;
  3. autouse 慎用:全局 autouse 容易出现多余前置,仅公共环境配置使用;
  4. scope=session 仅整个 pytest 命令执行一次,分开多次 pytest 执行会重复初始化。
相关推荐
Avan_菜菜8 小时前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB1 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode3 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220703 天前
如何搭建本地yum源(上)
运维
大树886 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠6 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质6 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工6 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智6 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_6 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化