fixture
fixture用途
1.用例编写前的初始化设置,连接数据库等
2.测试用例的前置条件可以使用fixture实现
3.实现unittest不能实现的功能,注入测试用例之间的参数传递
fixture与unittest区别:
1.独立命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活
2.按模块化的方式实现,每个fixture可以相互调用
3.fixture的范围从简单的单元测试到复杂的功能测试,可以对fixture配置参数,或者跨函数function、类class、模块modules或整个测试session的范围
fixture参数传入
1.单个fixture
# 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
# 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.互相调用
# 相互调用
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,作用范围内的每个测试用例运行之前运行一次
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运行之前运行一次
# 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文件所有用例开始前执行一次
# 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
# 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'])
# 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装饰器,
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可以叠加,注意先执行的放底层,后执行的放顶层
# 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()
# 叠加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
# 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语句使用。
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使用
import smtplib
import pytest
@pytest.fixture(scope="module")
def smtp():
with smtplib.SMTP("smtp.qq.com") as smtp:
yield smtp
addfinalizer终结函数
# 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

浙公网安备 33010602011771号