Pytest Fixture 作用域与接口测试 Token 污染问题实战解析

引言

在做接口自动化测试时,你可能遇到过这样的情况:

单独运行某个用例一切正常,但批量跑测试时,大量接口返回 401 或权限错误。

这通常是 fixture 生命周期与共享状态导致的问题。本文结合实际场景,带你深入理解 Pytest 的 fixture 作用域,并提供解决方案。


一、Pytest Fixture 的作用域

Pytest 提供了几种常用 fixture 生命周期(scope):

scope 创建次数 生命周期说明
function 每个测试用例 1 次 用例之间完全隔离
class 每个测试类 1 次 同一类用例共享
module 每个模块 1 次 同一文件的所有用例共享
session 整个测试运行 1 次 测试全局共享资源

本质理解

  • 短生命周期适合需要隔离状态的对象(如接口客户端、登录 token)
  • 长生命周期适合全局共享资源(如数据库连接、Redis 客户端)

二、真实问题复现

假设我们有两个 fixture:

python 复制代码
@pytest.fixture(scope="session")
def request_util():
    return RequestUtil()  # 封装 HTTP 请求,带 token 状态

@pytest.fixture(scope="session")
def auth_token(request_util, test_data):
    user = test_data["users"]["test_user"]
    resp = request_util.post("/public/login", json={
        "account": user["account"],
        "password": user["password"]
    })
    return resp.json()["data"]["token"]

问题表现

运行测试时,批量用例报错:

复制代码
ScopeMismatch: You tried to access the function scoped fixture request_util with a session scoped request object
Token 不匹配或已失效

分析:

  • request_util 携带 token 状态,每个用例可能修改 header
  • auth_token 是 session 级 fixture,全局依赖短生命周期 fixture → 生命周期冲突
  • 结果:多个用例共享同一个 request_util 与 token,状态污染 → 401

三、为什么 scope="function" 可以解决问题

1)改法示例

python 复制代码
@pytest.fixture(scope="function")
def request_util():
    return RequestUtil()

@pytest.fixture(scope="function")
def auth_token(request_util, test_data):
    user = test_data["users"]["test_user"]
    resp = request_util.post("/public/login", json={
        "account": user["account"],
        "password": user["password"]
    })
    return resp.json()["data"]["token"]

2)运行逻辑变化

原来(session):

复制代码
创建 request_util + token A(只一次)
用例1 → token A
用例2 → token A(被污染)
用例3 → token A(被污染)
...

改成 function:

复制代码
用例1 → 新 request_util → 登录 → token A
用例2 → 新 request_util → 登录 → token B
用例3 → 新 request_util → 登录 → token C
...

每个用例都是独立 session,token 不会相互污染 → 401 消失


四、什么时候用 session,什么时候用 function

✅ 适合 session(共享资源,不带状态)

python 复制代码
@pytest.fixture(scope="session")
def db_conn():
    return connect_mysql()

❌ 不适合 session(带状态对象)

python 复制代码
@pytest.fixture(scope="session")
def request_util():
    util = RequestUtil()
    util.login()  # 带 token 状态 → 多用例共享可能出问题
    return util
相关推荐
怕浪猫4 小时前
FDE 最大的浪费不是写出有 bug 的代码,而是漂亮地解决了一个错误的问题
面试·架构·github
AI情绪识别开源6 小时前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
黄敬峰7 小时前
Next.js 全栈实战:数据清洗、ORM 设计与 AI Prompt 工程最佳实践
面试·github
雨夜之寂11 小时前
雨夜-现在有办法识别是不是ai文章么
后端·面试
不正经学生12 小时前
C语言动态内存管理(上):堆上的自由与责任
c语言·开发语言·c++·算法·面试
ssshooter13 小时前
AI 时代你不能不知道的 git worktree
前端·后端·面试
CoderYanger13 小时前
A.每日一题:输入单词需要的最少按键次数 Ⅰ+Ⅱ
java·数据结构·算法·leetcode·面试
会周易的程序员14 小时前
aiDgeController 软PLC虚拟机stvm集成测试报告
c++·物联网·架构·集成测试·st·软plc·iec61131
测试老哥15 小时前
Postman获取token并设置token依赖步骤
自动化测试·软件测试·python·测试工具·测试用例·接口测试·postman
艾莉丝努力练剑18 小时前
【AI大模型接入SDK】SSE协议
c++·学习·面试·大模型·sdk