ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

pytest的fixture梳理

2026/8/18 19:11:52 拓冰建站 浏览量
pytest的fixture梳理 fixture特性夹具是在测试中用于提供共享资源、设置测试环境或模拟行为的工具。0、fixture的返回值0.1 核心结论无论 fixture 是否有返回值fixture 内部的函数都会完整执行。fixture 的所有调用都返回其返回值而不是函数本身。无论使用return、yield、无返回值返回None还是闭包模式测试中通过参数名获取的都是 fixture 的返回值。0.2 四种常用返回值模式0.2.1 return 返回值最常用importpytestpytest.fixturedefuser():return{name:张三,age:20}deftest_user(user):# user 是字典不是函数assertuser[name]张三assertuser[age]200.2.2 yield 返回值带清理importpytestpytest.fixturedefdb():print(连接数据库)conn{status:connected}yieldconn# 返回给测试print(关闭数据库)deftest_db(db):# db 是字典测试结束后自动清理assertdb[status]connected0.2.3 无返回值返回 Noneimportpytestpytest.fixturedefsetup():print(执行设置)# 没有 return默认返回 Nonedeftest_setup(setup):# setup 是 NoneassertsetupisNone0.2.4 闭包/工厂模式返回函数往fixture传参importpytestpytest.fixture(scopefunction)defprepared_patient(device_info,patient_login_page,studio_binding_page,package_detail_page):前置步骤启动微信 → 哈瑞特健康 → 管理计划 → 登录(手机号验证码) → 我的 → 扫一扫绑定工作室 → 推荐服务包详情 返回可调用对象传入 (phone,) 后执行def_prepare(phone,patient_info):log.info(f测试设备信息:{device_info})log.info(f开始测试患者端购买流程:{phone})patient_login_page.start_wechat(stopTrue)assertpatient_login_page.is_wechat_running(),微信启动失败patient_login_page.navigate_to_health()patient_login_page.login(phone)studio_binding_page.bind_studio()package_detail_page.open_package_detail(patient_info)return_prepare测试用例就可以往fixture里面传参 如phone patient_info 等参数对比总结模式写法测试中获取的值调用方式returnreturn valuevalue直接使用yieldyield valuevalue直接使用自动清理无返回值无 returnNone值永远为 None闭包/工厂return function函数对象调用函数获取新对象1. 可以重复使用多个用例可以使用同一个fixture2. 一个测试用例可以使用多个装置importpytest# Arrangepytest.fixturedeffirst_entry():returna# Arrangepytest.fixturedefsecond_entry():return2# Arrangepytest.fixturedeforder(first_entry,second_entry):return[first_entry,second_entry]2.1 如果多个装置存在yield,yield前先进先出yield后则是先进后出importpytestpytest.fixturedefa():print(hello)yieldprint(this is a)pytest.fixturedefb():print(world)yieldprint(this is b)deftest_demo(a,b):print(this is test_demo)if__name____main__:pytest.main([-sv,test1.py])3 需要self–把fixture写在函数内部classTestDeviceRecordManual:手动添加或更新心率血压记录_data_filedevice_record.yamlpytest.fixture(autouseTrue)def_setup(self,api_client):注入 api_client 到 self.apiself.apiapi_client4. fixfure多重嵌套如下append_first、test_string_only并且此fixture缓存即order如果一个 fixture 被请求了多次但它的作用范围是函数级别默认那么这个 fixture 在每次请求时都会重新执行一次而不会缓存。这会导致每次请求获得的数据都是独立的不受前一次请求的影响。所以一般不要使用缓存保证起独立性。所以一般不要使用缓存保证起独立性importpytest# Arrangepytest.fixturedeffirst_entry():returna# Arrangepytest.fixturedeforder():return[]# Actpytest.fixturedefappend_first(order,first_entry):order.append(first_entry)returnorderdeftest_string_only(append_first,order,first_entry):# Assertprint(append_first)# [a]print(order)# [a]assertorder[first_entry]pytest.main([-sv,test1.py])5自动使用fixture不需要请求设置和清理环境、全局配置例如数据库连接、日志设置等可以使用笔者用的不多importpytestpytest.fixturedeffirst_entry():returnapytest.fixture(autouseTrue)deforder():returnhello worlddeftest_a(order):print(order)pytest.main([-sv,test1.py])6 动态定义fixture范围7 安全拆卸的fixture8fixture的request9 fixture的参数化10 向fixture里传参此fixture带有参数get_time如何向fixture内传参呢pytest.fixture(scopefunction)defdust_alarm_param_single_more_80(get_time):崇州紫园get_time参数化生成告警get_timeget_time目前有两种方法实现1、通过pytest.mark.parametrize传参pytest.mark.parametrize(get_time,[(my_time.current_timestamp()[0] 1 * 3600)])函数def test_dust_alarm_001(cls, dust_alarm_init,get_time, dust_alarm_param_single_more_80)直接接受此参数注意一般将需要传入得参数get_time放在那个fixture的前面allure.feature(告警抑制)allure.story(夜间不告警)allure.title(0到085959之间产生告警 如1点崇州紫园省站超标80不告警)pytest.mark.parametrize(get_time,[(my_time.current_timestamp()[0]1*3600)])pytest.mark.debugdeftest_dust_alarm_001(cls,dust_alarm_init,get_time,dust_alarm_param_single_more_80):pass例子2pytest.mark.parametrize多次使用# conftest.pypytest.fixture(scopefunction)defillegal_alarm_init_test_illegal_sale_finished_sand(alarm_type):alarm_typealarm_type违规销售砂石成品料# 新加的5种类型print(alarm_type)del_sql1fdelete FROM alarm_dog WHERE type in ({alarm_type});print(del_sql1)try:db.delete(del_sql1)exceptExceptionase:log.error(e)可以看到成功打印出fixture的内容2、通过fixture传参把get_time写成一个fixture也可以实现这个fixture return一个数据即可如order会接收一个参数importpytest# Arrangepytest.fixturedeffirst_entry():print(hello)returna# Arrangepytest.fixturedeforder(first_entry):print(its ok)yieldfirst_entryprint(over)deftest_string_only(order):resultorderprint(result)assertresultapytest.main([-sv,1test.py]11 多重嵌套fixture时fixfure的作用域优先于fixture顺序存在以下fixturetest_demo(d, c, b, a):如果d,c,b,a都是function级别执行顺序应该是d,c,b,a由于是不同的范围因此按照范围大小执行顺序为及ab,c,d即session、module、class、functionimportpytest shipytest.fixture(scopesession)def a():print(my session)pytest.fixture(scopemodule)def b():print(my module)pytest.fixture(scopeclass)def c():print(my class)pytest.fixture(scopefunction)def d():print(my function)def test_demo(d,c,b,a): pass pytest.main([-sv,test1.py])