关键字 开发-11 yaml文件中添加fixture功能
前言
每一条pytest用例都可以添加fixture的前置功能,只需要在用例的参数中传入在conftest.py文件中写的函数的名称就可以实现每条用例的前置和后置。
1. yaml文件中加入fixture的功能
因为我们实现了动态生成测试用例,所以我们可以直接通过在生成动态用例的时候就传入该fixture函数名。在conftest.py文件中,我们写入fixture函数:
@pytest.fixture()
def run_fixt():
print('------------用例执行之前---------------')
yield
print('------------用例执行之后----------------')
之后在生成用例函数的时候,在函数中加入,用例前置的名称即可实现用例的前置后置功能。
f = create_function_from_parameters(func=execute_yaml_case,
parameters=[
Parameter('request', Parameter.POSITIONAL_OR_KEYWORD),
Parameter('requests_session', Parameter.POSITIONAL_OR_KEYWORD),
Parameter('base_url', Parameter.POSITIONAL_OR_KEYWORD),
Parameter('run_fixt', Parameter.POSITIONAL_OR_KEYWORD), # 添加用例前置后置功能
],
documentation=case_name,
func_name=case_name,
func_filename=f"{self.module.__name__}.py")
运行一下看看是否成功:pytest .\data\test_login.yml -s
上面的方式,我们是在生成用例函数的时候,写死进去的,不是特别灵活,我们可以通过写在yaml文件中的方式,来灵活传入用例前置后置功能。
1.1 在yaml中添加fixtures关键字
首先在,yaml中,添加fixtures的位置有2个,一个是config关键字中,另一个位置是在用例中。在config关键字中,我们在读取config数据的功能模块中添加如下的代码,获取到config下面的fixtures,
并且支持:fixtures:fun_fixtures1,fun_fixtures2或者[fun_fixtures1,fun_fixtures2]
def run(self):
# 1.先获取到config中的变量variables
if not self.raw.get('config'):
self.raw['config'] = {}
base_url = self.raw.get('config').get('base_url', None) # 获取config中base_url
config_variables = self.raw.get('config').get('variables',{})
log.info(f'获取到的config中的变量:{config_variables}')
# 收集config中的fixtures
config_fixtures = self.raw.get('config').get('fixtures', [])
# 多个则变成list形式存储
if isinstance(config_fixtures, str):
config_fixtures = config_fixtures.split(',')
同理,在测试用例处添加fixtures,并且在获取完用例中的fixtures之后,需要在动态函数生成之前和并config中的fixture,避免重复传入fixtures,影响用例的执行。
case = {} # 收集用例名称和执行内容
for case_name, case_value in self.raw.items():
log.info(f"用例执行内容case_value: {case_value}")
if case_name == 'config':
continue # 跳过config内容,非用例部分
if not str(case_name).startswith('test'):
case_name = 'test_' + str(case_name)
if isinstance(case_value, list): # 把测试用例放到用例容器case中
case[case_name] = case_value
else:
case[case_name] = [case_value] # 以list的形式加入到用例容器中case中
# 用例中的fixtures
if 'fixtures' in case[case_name][0]: # fixtures写在第一个步骤中
case_raw_fixtures = case[case_name][0].get('fixtures', [])
case_fixtures = render_template_obj.rend_template_any(case_raw_fixtures, **self.context)
# 如果有多个,则变成list的形式
if isinstance(case_fixtures, str): # fixtures: run_fixt or [run_fixt1, run_fixt2] --> list
case_fixtures = case_fixtures.split(',')
# 在动态函数生成之前合并config和case中的fixtures
fun_fixtures = []
fun_fixtures.extend(config_fixtures) # extend()传可迭代对象,append()传一个一个整体(单个元素)
[fun_fixtures.append(fixt) for fixt in case_fixtures if fixt not in fun_fixtures]
1.2 动态将合并后的fixtures传入到用例函数中
为了动态将fixturs参数传入用例函数中,我们需要单独编写一个动态生成生成动态函数所需要的parameters参数。于是我们写一个函数:function_parameters
,并且传入进去,如下所示:
f = create_function_from_parameters(func=execute_yaml_case,
parameters=self.function_parameters(fun_fixtures),
documentation=case_name,
func_name=case_name,
func_filename=f"{self.module.__name__}.py")
# 向 module中加入test 函数
setattr(self.module, case_name, f)
@staticmethod
def function_parameters(config_fixtures) -> list:
# 测试函数的默认请求参数
function_parameters = [Parameter('request', Parameter.POSITIONAL_OR_KEYWORD),
Parameter('base_url', Parameter.POSITIONAL_OR_KEYWORD)] # # 内置request and base_url fixture
# 获取传给用例的 fixtures
if isinstance(config_fixtures, str):
config_fixtures = [item.strip(' ') for item in config_fixtures.split(',')]
if not config_fixtures:
function_parameters.append(Parameter('requests_session', Parameter.POSITIONAL_OR_KEYWORD))
else:
if 'requests_function' in config_fixtures:
function_parameters.append(Parameter('requests_function', Parameter.POSITIONAL_OR_KEYWORD))
elif 'requests_module' in config_fixtures:
function_parameters.append(Parameter('requests_module', Parameter.POSITIONAL_OR_KEYWORD))
else:
function_parameters.append(Parameter('requests_session', Parameter.POSITIONAL_OR_KEYWORD)) # 自定义的fixtures
for fixture in config_fixtures:
if fixture not in ['requests_function', 'requests_module']:
function_parameters.append(Parameter(fixture, Parameter.POSITIONAL_OR_KEYWORD))
return function_parameters
在conftest.py文件中编写2个fixtures函数。
@pytest.fixture()
def run_fixt():
print('------------用例执行之前---------------')
yield
print('------------用例执行之后----------------')
@pytest.fixture()
def config_run_fixt():
print('------------config_fixtures用例执行之前---------------')
yield
print('------------config_fixtures用例执行之后----------------')
在yaml文件中,写入fixtures的关键字:
.\data\test_login.yml
config:
name: yaml申明变量
fixtures: config_run_fixt
variables:
username: "admin"
password: "Admin@22"
email11: ${email1}
data_int: 222
test_login:
name: 登录成功
fixtures: run_fixt
request:
url: /api/v1/auth/login
method: POST
json:
username: ${username}
password: ${password}
extract:
code1: $.code
code2: body.code
token: $.data.token
msg: '"message":"(.*?)"'
validate:
- eq: [$.code, "000000"]
- eq: [$.message, OK]
test_login2:
name: 登录失败
request:
url: /api/v1/auth/login
method: POST
json:
username: ${email11}
password: ${email2()}
data_value: ${int(str_to_int(34))}
2. 引用fixtures中的返回值
fixtures函数有些会有yield的返回值,那么如何获取?显示步骤如下:
1.将args参数添加到context容器中
2.渲染变量,从context中取出fixtures中的返回值
从图中可以知道,args参数中,有fixtures函数的返回值:'run_fixt': 'hello word'
于是我们可以将其添加context中,添加进去后,后面就是变量的渲染了。