承接前文 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再跑用例。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 可依赖其他 fixturepytest 自动按依赖顺序逐层执行适合分层初始化比如先创建订单→再创建订单商品。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多个前置资源并行加载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通用初始化 清理模板pytest.fixture def open_close(): # 前置用例执行前 print(前置初始化连接资源) yield 资源对象 # 返回值传给用例 # 后置用例执行完毕 print(后置销毁、关闭资源) def test_demo(open_close): print(执行测试用例使用{}.format(open_close))运行输出前置初始化连接资源 执行测试用例使用资源对象 后置销毁、关闭资源示例 2文件读写实战创建文件→读写→自动关闭pytest.fixture def file_handle(): # 前置打开文件 f open(test.txt,w,encodingutf-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 次类开头创建类全部跑完销毁一个模块下多个接口共用登录 tokenmodule单个 py 文件当前整个.py 脚本所有用例只初始化 1 次单个模块全局数据库连接session整个测试会话项目全部用例只执行 1 次全局整个自动化项目全局登录、环境初始化示例scopeclass 类级别复用pytest.fixture(scopeclass) 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 自动执行无需传参全局自动生效autouseTrue不用在用例形参填写 fixture 名称满足 scope 范围的所有用例自动执行该 fixture适合全局统一配置全项目统一初始化日志、全局环境变量。# 当前类下所有用例自动执行不用手动传参 pytest.fixture(scopeclass,autouseTrue) 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用例参数化侧重接口入参。# 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 全局配置文件项目级 fixture1. 规则文件名固定 conftest.py 不可修改放在项目目录同目录 子目录所有 py 脚本不用 import 导入直接调用文件内 fixture一般存放scopemodule/session全局 fixture全局登录、全局数据库连接实现跨文件前后置复用。项目目录结构项目根目录 ├─ conftest.py # 全局fixture ├─ test_case1/ │ └─ test_api1.py └─ test_case2/ └─ test_api2.pyconftest.py 代码pytest.fixture(scopesession) def global_env(): print(【全局session】整个项目只初始化一次环境) yield print(【全局销毁】项目所有用例跑完清理环境)test_api1.py 直接使用def test_demo(global_env): pass八、Fixture 和 parametrize 参数化选型区别pytest.mark.parametrize用例入参参数化侧重接口请求参数、业务入参变化fixture(params)前置资源参数化侧重测试环境、前置准备数据变化不同测试账号、不同测试环境。九、接口自动化综合实战整合前文前后置 fixture 断言import pytest,requests # 全局登录fixture pytest.fixture(scopemodule) def get_token(): # 前置登录接口拿token login_url https://jsonplaceholder.typicode.com/users/1 res requests.get(login_url) token ftoken_{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,headersheaders) # 断言 assert res.status_code 200,接口请求失败 assert res.json()[userId] 1十、高频踩坑总结yield 前后代码严格分开yield 前前置、yield 后后置异常时 yield 之后代码依然会执行conftest 就近原则子目录 conftest 优先级高于根目录就近调用autouse 慎用全局 autouse 容易出现多余前置仅公共环境配置使用scopesession 仅整个 pytest 命令执行一次分开多次 pytest 执行会重复初始化。
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再跑用例。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 可依赖其他 fixturepytest 自动按依赖顺序逐层执行适合分层初始化比如先创建订单→再创建订单商品。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多个前置资源并行加载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通用初始化 清理模板pytest.fixture def open_close(): # 前置用例执行前 print(前置初始化连接资源) yield 资源对象 # 返回值传给用例 # 后置用例执行完毕 print(后置销毁、关闭资源) def test_demo(open_close): print(执行测试用例使用{}.format(open_close))运行输出前置初始化连接资源 执行测试用例使用资源对象 后置销毁、关闭资源示例 2文件读写实战创建文件→读写→自动关闭pytest.fixture def file_handle(): # 前置打开文件 f open(test.txt,w,encodingutf-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 次类开头创建类全部跑完销毁一个模块下多个接口共用登录 tokenmodule单个 py 文件当前整个.py 脚本所有用例只初始化 1 次单个模块全局数据库连接session整个测试会话项目全部用例只执行 1 次全局整个自动化项目全局登录、环境初始化示例scopeclass 类级别复用pytest.fixture(scopeclass) 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 自动执行无需传参全局自动生效autouseTrue不用在用例形参填写 fixture 名称满足 scope 范围的所有用例自动执行该 fixture适合全局统一配置全项目统一初始化日志、全局环境变量。# 当前类下所有用例自动执行不用手动传参 pytest.fixture(scopeclass,autouseTrue) 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用例参数化侧重接口入参。# 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 全局配置文件项目级 fixture1. 规则文件名固定 conftest.py 不可修改放在项目目录同目录 子目录所有 py 脚本不用 import 导入直接调用文件内 fixture一般存放scopemodule/session全局 fixture全局登录、全局数据库连接实现跨文件前后置复用。项目目录结构项目根目录 ├─ conftest.py # 全局fixture ├─ test_case1/ │ └─ test_api1.py └─ test_case2/ └─ test_api2.pyconftest.py 代码pytest.fixture(scopesession) def global_env(): print(【全局session】整个项目只初始化一次环境) yield print(【全局销毁】项目所有用例跑完清理环境)test_api1.py 直接使用def test_demo(global_env): pass八、Fixture 和 parametrize 参数化选型区别pytest.mark.parametrize用例入参参数化侧重接口请求参数、业务入参变化fixture(params)前置资源参数化侧重测试环境、前置准备数据变化不同测试账号、不同测试环境。九、接口自动化综合实战整合前文前后置 fixture 断言import pytest,requests # 全局登录fixture pytest.fixture(scopemodule) def get_token(): # 前置登录接口拿token login_url https://jsonplaceholder.typicode.com/users/1 res requests.get(login_url) token ftoken_{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,headersheaders) # 断言 assert res.status_code 200,接口请求失败 assert res.json()[userId] 1十、高频踩坑总结yield 前后代码严格分开yield 前前置、yield 后后置异常时 yield 之后代码依然会执行conftest 就近原则子目录 conftest 优先级高于根目录就近调用autouse 慎用全局 autouse 容易出现多余前置仅公共环境配置使用scopesession 仅整个 pytest 命令执行一次分开多次 pytest 执行会重复初始化。