用文件extract.yml保存中间变量,以字典的格式写入。
一、YML文件操作
安装PyYAML库。
我的文件路径./commons/yaml_util.py,这里我没有使用os.getcwd()
def path(relative_path=''):
"""
根据文件的相对路径获取绝对路径
:param relative_path: 相对于项目根目录。不传参时返回项目根目录。
:return:
"""
# 该文件所在目录的绝对路径
dirname = os.path.dirname(os.path.realpath(__file__))
# 上一级目录即项目根目录+文件相对路径
path_str = os.path.join(dirname, '..', relative_path)
print(path_str)
return os.path.realpath(path_str)
def yaml_dump(data):
"""
把从响应中提取的数据以追加的方式写入extract.yml文件。以字典的格式写入。
:param data:
:return:
"""
with open(path('extract.yml'), 'a', encoding='utf-8') as stream:
yaml.dump(data, stream, allow_unicode=True)
def get(key):
"""
读取extract.yml,内容是字典格式。通过key获取字段的值
:param key:
:return:
"""
# extract.yml文件存在
if os.path.exists(path('extract.yml')):
load = yaml_load('extract.yml')
if load is not None and (key in load):
return load[key]
return None
def yaml_load(relative_path):
"""
读取YML文件全部内容
:param relative_path 相对于项目根目录
:return: 文件没有内容返回None
"""
with open(path(relative_path), 'r', encoding='utf-8') as stream:
return yaml.load(stream, yaml.FullLoader)
def yaml_clear():
"""
清空extract.yml。在conftest.py添加session级别夹具,用例执行前自动清空
:return:
"""
with open(path('extract.yml'), 'w') as stream:
stream.truncate()
二、提取响应中的字段
- 使用正则表达式去字符串中匹配。使用re库
- 使用jsonpath表达式去提取json响应中的字段。使用jsonpath库
- YML用例参考:
-
title: 登陆成功用例
request:
method: post
url: ?s=user/login
params:
json:
extract:
token: $.data.token
nickname: '"nickname":"(.*?)"'
validate:
- 提取方法:
def raise_exc(self, msg):
"""
打印日志并抛异常
:param msg:
:return:
"""
logger.error(msg)
raise Exception(msg)
def extract_data(self, rsp, extract_dict: dict):
"""
提取中间变量
:param rsp: 响应
:param extract_dict: 需要提取的字段,对应YML用例extract节点
:return:
"""
for key, value in extract_dict.items():
# 正则提取,对字符串进行操作
if "(.*?)" in value or ("(.+?)" in value):
findall_list = re.findall(value, rsp.text)
# 没匹配到返回空列表[]
if len(findall_list) == 0:
self.raise_exc(f"正则表达式:{value}没匹配到数据")
elif len(findall_list) == 1:
# 以字典格式写入extract.yml
yaml_dump({key: findall_list[0]})
logger.info('提取的中间变量%s' % {key: findall_list[0]})
else:
yaml_dump({key: findall_list})
logger.info('提取的中间变量%s' % {key: findall_list})
# jsonpath提取
else:
try:
# 如果响应不是json会抛出异常。另外rsp.json()是字典
rsp_json = rsp.json()
except Exception:
self.raise_exc(f"响应不是json格式。jsonpath:{value}没有提取到数据")
else:
jsonpath_value_list = jsonpath.jsonpath(rsp_json, value)
# 没提取到返回False
if jsonpath_value_list:
if len(jsonpath_value_list) == 1:
yaml_dump({key: jsonpath_value_list[0]})
logger.info('提取的中间变量%s' % {key: jsonpath_value_list[0]})
else:
yaml_dump({key: jsonpath_value_list})
logger.info('提取的中间变量%s' % {key: jsonpath_value_list})
else:
self.raise_exc(f"jsonpath:{value}没有提取到数据")
三、执行用例前清空extract.yml
conftest.py
@pytest.fixture(scope="session", autouse=True)
def clear_extract():
yaml_util.yaml_clear()