代码示例
def specification_yaml(self, base_info, test_case):
"""
接口请求处理基本方法
:param base_info: yaml文件里面的baseInfo
:param test_case: yaml文件里面的testCase
:return:
"""
try:
params_type = ['data', 'json', 'params']
url_host = self.conf.get_section_for_data('api_envi', 'host')
api_name = base_info['api_name']
allure.attach(api_name, f'接口名称:{api_name}', allure.attachment_type.TEXT)
url = url_host + base_info['url']
allure.attach(api_name, f'接口地址:{url}', allure.attachment_type.TEXT)
method = base_info['method']
allure.attach(api_name, f'请求方法:{method}', allure.attachment_type.TEXT)
header = self.replace_load(base_info['header'])
allure.attach(api_name, f'请求头:{header}', allure.attachment_type.TEXT)
# 处理cookie
cookie = None
if base_info.get('cookies') is not None:
cookie = eval(self.replace_load(base_info['cookies']))
case_name = test_case.pop('case_name')
allure.attach(api_name, f'测试用例名称:{case_name}', allure.attachment_type.TEXT)
# 处理断言
val = self.replace_load(test_case.get('validation'))
test_case['validation'] = val
validation = eval(test_case.pop('validation'))
# 处理参数提取
extract = test_case.pop('extract', None)
extract_list = test_case.pop('extract_list', None)
# 处理接口的请求参数
for key, value in test_case.items():
if key in params_type:
test_case[key] = self.replace_load(value)
# 处理文件上传接口
file, files = test_case.pop('files', None), None
if file is not None:
for fk, fv in file.items():
allure.attach(json.dumps(file), '导入文件')
files = {fk: open(fv, mode='rb')}
res = self.run.run_main(name=api_name, url=url, case_name=case_name, header=header, method=method,
file=files, cookies=cookie, **test_case)
status_code = res.status_code
allure.attach(self.allure_attach_response(res.json()), '接口响应信息', allure.attachment_type.TEXT)
try:
res_json = json.loads(res.text) # 把json格式转换成字典字典
if extract is not None:
self.extract_data(extract, res.text)
if extract_list is not None:
self.extract_data_list(extract_list, res.text)
# 处理断言
self.asserts.assert_result(validation, res_json, status_code)
except JSONDecodeError as js:
logs.error('系统异常或接口未请求!')
raise js
except Exception as e:
logs.error(e)
raise e
except Exception as e:
raise e
specification_yaml
方法解析
该方法用于处理 YAML 文件中定义的接口测试用例,包括请求参数构造、动态变量替换、接口调用、响应断言以及数据提取等核心功能。
方法定义
def specification_yaml(self, base_info, test_case):
"""
接口请求处理基本方法
:param base_info: yaml文件里面的baseInfo(接口基本信息)
:param test_case: yaml文件里面的testCase(测试用例数据)
:return: 无返回值,但通过断言验证接口行为
"""
步骤详解
1. 定义常量与基础配置
params_type = ['data', 'json', 'params']
url_host = self.conf.get_section_for_data('api_envi', 'host')
params_type
:表示请求参数可能包含的类型字段。url_host
:从配置文件中获取当前环境的主机地址。
2. 提取接口基本信息并添加 Allure 报告附件
api_name = base_info['api_name']
allure.attach(api_name, f'接口名称:{api_name}', allure.attachment_type.TEXT)
url = url_host + base_info['url']
allure.attach(api_name, f'接口地址:{url}', allure.attachment_type.TEXT)
method = base_info['method']
allure.attach(api_name, f'请求方法:{method}', allure.attachment_type.TEXT)
- 从
base_info
中提取接口名称、URL 和请求方法。 - 使用
allure.attach
将这些信息附加到 Allure 报告中,便于测试结果查看。
3. 处理请求头和 Cookie
header = self.replace_load(base_info['header'])
allure.attach(api_name, f'请求头:{header}', allure.attachment_type.TEXT)
cookie = None
if base_info.get('cookies') is not None:
cookie = eval(self.replace_load(base_info['cookies']))
- 调用
replace_load
对 header 进行变量替换。 - 如果存在 cookies,则同样进行替换并使用
eval
转换为字典格式。
4. 提取测试用例名称并添加报告附件
case_name = test_case.pop('case_name')
allure.attach(api_name, f'测试用例名称:{case_name}', allure.attachment_type.TEXT)
- 从
test_case
中提取用例名称并删除原始字段。 - 添加到 Allure 报告中。
5. 处理断言逻辑
val = self.replace_load(test_case.get('validation'))
test_case['validation'] = val
validation = eval(test_case.pop('validation'))
- 替换断言表达式中的变量。
- 使用
eval
执行断言表达式,生成实际断言规则。
6. 提取数据字段(extract / extract_list)
extract = test_case.pop('extract', None)
extract_list = test_case.pop('extract_list', None)
- 从
test_case
中提取需要提取的字段名,供后续从响应中提取数据。
7. 处理请求参数(data/json/params)
for key, value in test_case.items():
if key in params_type:
test_case[key] = self.replace_load(value)
- 遍历所有测试用例参数,若为
data
、json
或params
类型,则对其值进行变量替换。
8. 处理文件上传
file, files = test_case.pop('files', None), None
if file is not None:
for fk, fv in file.items():
allure.attach(json.dumps(file), '导入文件')
files = {fk: open(fv, mode='rb')}
- 如果存在
files
字段,表示是文件上传接口。 - 使用
open(..., mode='rb')
读取文件内容,并附加到 Allure 报告中。
9. 发送接口请求
res = self.run.run_main(name=api_name, url=url, case_name=case_name, header=header,
method=method, file=files, cookies=cookie, **test_case)
status_code = res.status_code
allure.attach(self.allure_attach_response(res.json()), '接口响应信息', allure.attachment_type.TEXT)
- 调用
run_main
方法发送请求。 - 获取状态码和响应内容。
- 将响应内容附加到 Allure 报告中。
10. 处理响应与断言
try:
res_json = json.loads(res.text) # 把json格式转换成字典
if extract is not None:
self.extract_data(extract, res.text)
if extract_list is not None:
self.extract_data_list(extract_list, res.text)
# 处理断言
self.asserts.assert_result(validation, res_json, status_code)
except JSONDecodeError as js:
logs.error('系统异常或接口未请求!')
raise js
except Exception as e:
logs.error(e)
raise e
- 将响应内容转为 JSON 字典。
- 若有
extract
或extract_list
,则调用对应方法提取数据。 - 使用断言方法对响应结果进行验证。
11. 异常捕获
except Exception as e:
raise e
- 捕获所有异常并重新抛出,确保测试框架可以正确识别失败情况。
示例说明
假设 YAML 文件如下:
baseInfo:
api_name: 登录接口
url: /login
method: POST
header:
Content-Type: application/json
cookies: null
testCase:
- case_name: 正常登录
json:
username: admin
password: ${get_password()}
validation:
code == 200 and msg == "success"
extract:
token: $.data.token
经过 specification_yaml
处理后:
${get_password()}
会被替换成实际密码。- 请求会携带正确的 JSON 数据。
- 响应中的
token
会被提取保存。 - 断言会检查是否返回预期结果。