注意
pytest版本升级到7.4.0版本之后,conftest.py文件搜索机制发生改变,默认从测试用例的目录去找对应的文件
介绍
fixture属于pytest中的一个方法。fixture可以用作测试用例的前置和后置操作,其中fixture命令规范没有像setup和teardown固定格式。可以随意命名。控制fixture的前置和后置操作是通过yield关键字进行来区分的,代码在yield前面的属于前置操作,代码在yield后面的属于后置操作。并且fixture也没有强烈的要求必须要前后置同时存在,可以只存在前置也可以只存在后置。fixture如果有后置内容,无论遇到什么问题,都会进行执行后置的代码。fixture可以实现unittest不能实现的功能,比如unittest中的测试用例和测试用例之间是无法传递参数和数据的,但是fixture却可以解决这个问题。
常见的应用场景
@pytest.fixture可以用在selenium中测试用例执行前后打开、关闭浏览器的操作; yield返回driver对象去操作浏览器;
@pytest.fixture可以用在接口自动化测试中操作登录,yield返回token;
测试用例调用fixture三种方式
- 将 fixture 名称作为测试用例函数的输入参数
- 用fixture decorator调用fixture,加上装饰器:@pytest.mark.usefixtures(fixture_name)
- fixture 设置 autouse=True
# 第一种:将fixture名称作为测试用例函数的输入参数
import pytest
@pytest.fixture()
def my_fixture():
return "666"
# fixture 中传递参数给测试用例
def test_my_fixture(my_fixture):
assert "666" == my_fixture
# 第二种:用fixture decorator调用fixture,加上装饰器:@pytest.mark.usefixtures(fixture_name)
import pytest
@pytest.fixture(scope='module')
def my_fixture():
print("\n前置")
yield
print("\n后置")
# 第一种是每个函数前声明.调用函数前先调用my_fixture函数
@pytest.mark.usefixtures("my_fixture")
def test_001():
print('test_001()')
# 第二种是封装在类里,类里的每个成员函数声明,将 fixture名称作为测试用例函数的输入参数
class TestLogin01:
@pytest.mark.usefixtures("my_fixture")
def test_002(self):
print('test_3()')
# 第三种是封装在类里在前声明,@pytest.mark.usefixtures(fixture_name)
@pytest.mark.usefixtures("my_fixture")
class TestLogin02:
def test_003(self):
print('test_003')
if __name__ == '__main__':
pytest.main()
# 第三种:fixture 设置 autouse=True
import time
import pytest
@pytest.fixture(scope="module", autouse=True)
def mod_header(request):
print('\n-----------------')
print('module : %s' % request.module.__name__)
print('-----------------')
@pytest.fixture(scope="function", autouse=True)
def func_header(request):
print('\n-----------------')
print('function : %s' % request.function.__name__)
print('time : %s' % time.asctime())
print('-----------------')
def test_one():
print('in test_one()')
def test_two():
print('in test_two()')
return和yeild的区别
都是表示返回值的意思,但是return的后面不能有代码,yeild很后面可以有代码
yield语句之前的就会在测试用例之前使用,yield之后的语句就会在测试用例执行完成之后再执行。
fixture传参数request
大部分的用例都会先登录,就需要把登录单独抽出来写个函数,其他用例全部调用这个登录函数就行,但是登录的账号不能写死。
request.cls 获取当前测试用例类,并访问类的属性和方法
import pytest
@pytest.fixture
def test_data(request):
# 获取当前测试用例类
test_class = request.cls
# 访问测试用例类的属性
assert test_class.attribute == 'value'
# 调用测试用例类的方法
# print(test_class.method())
# 返回测试数据
return {
'username': 'admin',
'password': '123456'
}
@pytest.mark.usefixtures("test_data")
class TestClass:
def setup(self):
self.name = "xs"
attribute = 'value'
age = 22
def method(self):
print('Method called from TestClass')
def test_example(self):
# 使用传递的测试数据进行测试
assert test_data['username'] == 'admin'
assert test_data['password'] == '123456'
fixture 中传递参数给测试用例
import pytest
@pytest.fixture
def test_data():
return {
'username': 'admin',
'password': '123456'
}
def test_login(test_data):
# 使用传递的参数进行测试
assert test_data['username'] == 'admin'
assert test_data['password'] == '123456'
conftest.py和 @pytest.fixture()结合使用实现全局的前置应用
- conftest.py 配置文件使用fixture不需要导入
- 可以在不同的py文件中使用同一个fixture
- 如果存在多个conftest.py文件测试用例会找到最近的conftest.py文件
fixture函数作用域
@pytest.fixture(scope=“”,params=“”,autouse=“”,ids=“”,name=“”)
- scope作用域 function(默认)、class、module、package、session
- params:参数化数据格式(list,tuple,字典列表[{},{}],字典元组({},{}))
- autouse=“True”:自动执行,默认False
- ids:当使用parames参数化时,给每一个值设置一个变量名,意义不大
- name:装饰器方法的别名
setup/teardown(每个用例前后),setup_class/teardown_class(每个类前后)
import pytest
class TestLogin01:
# 在所有用例前执行一次
def setup(self):
print("\n测试用例前执行")
# 在所有用例前执行一次
def setup_class(self):
print("\n测试类前")
def test_01(self):
print("\n测试用例01")
def test_02(self):
print("\n测试用例02")
def teardown(self):
print("\n测试用例后")
def teardown_class(self):
print("\n测试类后")
if __name__ == '__main__':
pytest.main()