fixture
fixture用途
1.用例编写前的初始化设置,连接数据库等
2.测试用例的前置条件可以使用fixture实现
3.实现unittest不能实现的功能,注入测试用例之间的参数传递
fixture与unittest区别:
1.独立命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活
2.按模块化的方式实现,每个fixture可以相互调用
3.fixture的范围从简单的单元测试到复杂的功能测试,可以对fixture配置参数,或者跨函数function、类class、模块modules或整个测试session的范围
fixture参数传入
1.单个fixture
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # test_fixture.py import pytest @pytest.fixture() def fixtureFunc(): a = 1 b = 2 return (a, b) def test_fixture(fixtureFunc): a = fixtureFunc[0] b = fixtureFunc[1] assert a == 1 assert b == 2 print( "调用了{}" .format(fixtureFunc)) class TestFixture( object ): def test_fixture_class(self, fixtureFunc): a = fixtureFunc[0] assert a == 1 print( '在类中使用fixture "{}"' .format(fixtureFunc)) if __name__== '__main__' : pytest.main([ '-s' , 'test_fixture.py' ]) |

2.使用多个fixture
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # test_fixture.py import pytest @pytest.fixture() def test1(): a = 1 return a @pytest.fixture() def test2(): b = 2 return b def test_fixture(test1, test2): a = test1 b = test2 assert a+b == 3 print( "调用了{}" .format(test1, test2)) class TestFixture( object ): def test_fixture_class(self, test1, test2): a = test1 assert a == 1 print( '在类中使用fixture "{}"' .format(test1)) if __name__== '__main__' : pytest.main([ '-s' , 'test_fixture.py' ]) |
3.互相调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # 相互调用 import pytest @pytest.fixture() def test1(): a = 1 a2 = a * a print( 'a的平方为{}' .format(a2)) return a2 def test2(test1): assert test1 == 1 print( 'test1使用成功' ) if __name__ == '__main__' : pytest.main( '-s test_fixture.py' ) |

fixture scope
function:每个test都运行,默认值是function,作用范围内的每个测试用例运行之前运行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import pytest @pytest.fixture() def test1(): a = 2 b = 'aaa' print( '传入a,b' ) return a, b def test2(test1): c = 'aaa' d = test1[1] print( 'test1使用成功' ) assert c == d def test2(test1): c = 2 assert c == test1[0] print( 'test1使用成功' ) if __name__ == '__main__' : pytest.main( '-v test_fixture.py' ) |
class:如果一个class中有多个用例度调用了fixture,那在此class运行之前运行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # scope='class' import pytest @pytest.fixture(scope= 'class' ) def test1(): a = 2 b = 'aaa' print( '传入a,b' ) return a, b class Testcase: def test2(self, test1): c = 'aaa' d = test1[1] print( 'test1使用成功' ) assert c == d def test3(self, test1): c = 2 assert c == test1[0] print( 'test3使用成功' ) if __name__ == '__main__' : pytest.main( '-v test_fixture.py' ) |
module:在当前.py文件所有用例开始前执行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # scope = 'module' import pytest @pytest.fixture(scope= 'module' ) def test1(): a = 2 b = 'aaa' c = '呀谁啦累' print( '传入a,b' ) return a, b, c class Testcase: def test2(self, test1): c = 'aaa' d = test1[1] print( 'test1使用成功' ) assert c == d def test3(self, test1): c = 2 assert c == test1[0] print( 'test3使用成功' ) def test4(): d = '呀' e = test1[2] f = d in e assert f if __name__ == '__main__' : pytest.main( '-v test_fixture.py' ) |
session:跨.py文件调用,当多个.py文件只需要调用一次fixture时,设置scope='session'并写入到conftest中
conftest.py文件名称是固定的pytest会自动识别该文家 ,放在项目的根目录下用以全局调用,对当前所在文件夹下的文件有效
# conftest.py import pytest @pytest.fixture(scope='module') def test1(): a = 2 b = 'aaa' c = '呀谁啦累' print('传入a,b') return a, b, c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # test_1.py import pytest class Testcase: def test2(self, test1): c = 'aaa' d = test1[1] print( 'test2执行成功' ) assert c == d def test3(self, test1): c = 2 assert c == test1[0] print( 'test3执行成功' ) if __name__ == '__main__' : pytest.main([ '-s' , 'test_1.py' ]) |
1 2 3 4 5 6 7 8 9 10 11 | # test_2.py import pytest def test4(test1): d = '呀谁啦累' e = test1[2] print( "test4执行成功" ) assert d == e if __name__ == '__main__' : pytest.main([ '-s' , 'test_2.py' ]) |
fixture调用方法
1.fixture的名字直接作为测试用例的参数
编写时,被调用方法前要使用@pytest.fixture装饰器,
1 2 3 4 5 6 7 8 9 10 11 | import pytest @pytest.fixture() def fixtureFunc(): return 'fixtureFunc' def test_fixture(fixtureFunc): print( '我调用了{}' .format(fixtureFunc)) if __name__== '__main__' : pytest.main([ '-s' , 'test_fixture.py' ]) |

2.使用@pytest.mark.userfixtures('fixture')装饰器
每个使用fixture函数的函数或类前都使用@pytest.mark.userfixtures('fixture')装饰器装饰
usefixture可以叠加,注意先执行的放底层,后执行的放顶层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # test_fixture.py import pytest @pytest.fixture() def fixtureFunc(): # print('\n fixture->fixtureFunc') return 'fixture' @pytest.mark.usefixtures( 'fixtureFunc' ) def test_fixture(): print( 'in test_fixture' ) @pytest.mark.usefixtures( 'fixtureFunc' ) class TestFixture( object ): def test_fixture_class(self): print( 'in class with text_fixture_class' ) if __name__== '__main__' : pytest.main([ '-s' , 'test_fixture.py' ]) |

叠加使用@pytest.mark.userfixtures()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # 叠加usefixture import pytest @pytest.fixture() def test1(): print( 'a=1' ) @pytest.fixture() def test2(): print( 'b=2' ) @pytest.mark.usefixtures( 'test2' ) @pytest.mark.usefixtures( 'test1' ) def test_fixture(): print( "调用了" ) @pytest.mark.usefixtures( 'test1' ) @pytest.mark.usefixtures( 'test2' ) class TestFixture( object ): def test_fixture_class(self): print( '在类中使用fixture' ) if __name__== '__main__' : pytest.main([ '-s' , 'test_fixture.py' ]) |
3.使用autouse参数(自动调用fixture)
在@pytest.fixture()中加入autouse参数,设置值为True
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # test_fixture.py import pytest @pytest.fixture(autouse=True) def fixtureFunc(): # print('\n fixture->fixtureFunc') return 'fixture' def test_fixture(): print( 'in test_fixture' ) class TestFixture( object ): def test_fixture_class(self): print( 'in class with text_fixture_class' ) if __name__== '__main__' : pytest.main([ '-s' , 'test_fixture.py' ]) |
conftest.py
作用范围:对当前文件夹下的文件生效,若该文件在根目录中,则起全局作用
注意:
conftest在不同位置,作用域也不一样
conftest不能跨模块调用
fixture实现teardown
1.在fixture中添加yield,用以唤醒teardown执行内容
注:如果其中一个用例执行异常,不会影响yield后的teardown执行,运行结果互不影响;
但如果在setup(即open函数中yield之前的部分)就出现异常,不会去执行teardown;
yield可以配合with语句使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import pytest @pytest.fixture(scope= 'module' ) def open(): print( "第一步" ) yield print( "执行teardown" ) def test1(open): print( "用例一" ) assert 1==2 raise AssertionError def test2(open): print( "用例二" ) if __name__ == "__main__" : pytest.main([ '-s' , 'test_fixture.py' ]) |
结合with使用
1 2 3 4 5 6 7 | import smtplib import pytest @pytest.fixture(scope= "module" ) def smtp(): with smtplib.SMTP( "smtp.qq.com" ) as smtp: yield smtp |
addfinalizer终结函数
1 2 3 4 5 6 7 8 9 10 11 12 | # yield配合with语句使用 import smtplib import pytest @pytest.fixture(scope= "module" ) def smtp_connection(request): smtp_connection = smtplib.SMTP( "smtp.gmail.com" , 587, timeout=5) def fin(): print( "teardown smtp_connection" ) smtp_connection.close() request.addfinalizer(fin) return smtp_connection |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署