什么是断言:
功能:Python内置的assert语句(断言)可以用来自动检测Python程序中的错误,让程序更可靠更易于调试。
含义:断言语句是一种调试工具,用来测试某个断言条件,如果断言条件为真,则程序将继续正常执行;如果条件为假,则会引发AssertionError异常并显示相关错误信息。
接口中断言:
接口断言一般有两种,一种是通过返回值的状态码是否等于200,一种是业务的判断,业务判断可以使用两种方式,一种是想等,一种是包含
1、状态断言:返回的状态码是否等于200
2、业务断言:相等的断言、包含的断言
1、yaml文件中添加接口断言的值
-
name: 文件上传接口
request:
method: post
url: /cgi-bin/media/uploadimg?access_token=${reads_token_yaml(access_token)}
files: {media: "D:\\picture\\4.png"}
#断言
validate:
#状态断言
- equals: {status_code: 200}
#业务断言-包含
- contains: url
2、在同一请求方法中,进行断言方法的封装
虽然在yaml文件中已经编写了需要断言的值,在封装断言的时候需要添加一个值(flag_all、flag),来断言他最终的返回结果是否为零,当不0,接口会报fail,
如果不添加值,接口只会判断yaml文件中需要断言的值,是否与接口返回值一致,如不一致,只会返回报错信息,不会报fail,而是pass
2.1、首先在封装yaml方法里面添加一个断言方法
#yaml文件封装
def send_yaml(self,arges_name):
yaml_key = arges_name.keys()
if "name" in yaml_key and "request" in yaml_key:
yaml_request=arges_name["request"]
request_key = yaml_request.keys()
if "method" in request_key and "url" in request_key:
method=yaml_request.pop("method")
url=yaml_request.pop("url")
res=self.send_request(method,url,**arges_name["request"])
res_text=res.text
#状态码
res_status=res.status_code
res_json=""
try:
res_json = res.json()
except Exception as e:
print("jsonpath数据类型必须是json格式")
if "extract" in yaml_key:
for key,values in arges_name["extract"].items():
if "(.*?)" in values or "(.+?)" in values:
zz_value=re.search(values,res_text)
if zz_value:
write_token_yaml({key:zz_value.group(1)})
else:
jp_values=jsonpath.jsonpath(res_json,values)
if jp_values:
write_token_yaml({key:jp_values[0]})
#断言方法,arges_name["validate"]为yaml文件中需要断言的所有值
#res_json 为接口返回的值
#res_status 为接口返回的状态码
self.assert_result(arges_name["validate"],res_json,res_status)
else:
print("request中缺少关键字段:name,request")
else:
print("yaml文件第一阶段缺少关键字段:name,request")
2.2、写一个断言的方法
#断言
def assert_result(self,yq_result,sj_result,res_status):
flag_all = 0
# 循环得到yaml文件的数据列表
for yq in yq_result:
#循环输出字典中的键值对
for key,value in yq.items():
#如果键等于equals
if key == "equals":
flag = self.assert_equals(value,res_status,sj_result)
flag_all = flag_all+flag
elif key == "contains":
flag = self.assert_cintains(value,sj_result)
flag_all = flag_all+flag
else:
print("该断言还未添加,暂不支持")
assert flag_all == 0
2.3、编写 等于 和 包含方法
#断言-等于
def assert_equals(self,value,res_status,sj_result):
flag = 0
for key,value in value.items():
#断言状态是否与预期一致
if key == "status_code":
if res_status != value:
flag = flag+1
print(f"断言失败,预期状态码{value}与返回状态码{res_status}不一致")
else:
assert_value=jsonpath.jsonpath(sj_result,f"$..{key}")
if assert_value:
if value not in assert_value:
flag = flag+1
print(f"断言失败,{key}不等于{value}")
else:
flag = flag+1
print(f"{key}不存在")
return flag
#断言_包含
def assert_cintains(self,value,sj_result):
flag = 0
if value not in str(sj_result):
flag=flag+1
print(f"断言失败{value}不存在{sj_result}中")
return flag
总体代码
#!/usr/bin/python
# -*- coding: UTF-8 -*
import json
import re
import jsonpath
import requests
from debug_talk import DebugTalk
from tools.yaml_tool import read_base_url_yaml, write_token_yaml, read_token_yaml
class Unifiedrequest:
def __init__(self,two,obj):
self.url=read_base_url_yaml("base",two)
self.obj=obj
#数据替换,data为获取到${}中的数据
#数据类型可能(string,int,float,list,dict),需要先数据转换
def read_token(self,data):
if data:
#保存原数据类型
data_type=type(data)
#数据类型转换
if isinstance(data,dict) or isinstance(data,list):
str_data=json.dumps(data)
else:
str_data=str(data)
for ce in range(1,str_data.count("${")+1):
if "${" in str_data and "}" in str_data:
index=str_data.index("${")
indexend=str_data.index("}",index)
old_value=str_data[index:indexend+1]
#获取对象属性
fun_name=old_value[2:old_value.index("(")]
fun_values=old_value[old_value.index("(")+1:old_value.index(")")]
fun_values_new=fun_values.split(",")
#*fun_values_new 解包 列表
if fun_values_new != " ":
#getattr() 函数用于返回一个对象属性值。
new_value=getattr(self.obj,fun_name)(*fun_values_new)
str_data=str_data.replace(old_value,str(new_value))
else:
new_value = getattr(self.obj,fun_name)()
str_data = str_data.replace(old_value, str(new_value))
if isinstance(data,dict) or isinstance(data,list):
data=json.loads(str_data)
else:
data=data_type(str_data)
return data
#yaml文件封装
def send_yaml(self,arges_name):
yaml_key = arges_name.keys()
if "name" in yaml_key and "request" in yaml_key:
yaml_request=arges_name["request"]
request_key = yaml_request.keys()
if "method" in request_key and "url" in request_key:
method=yaml_request.pop("method")
url=yaml_request.pop("url")
res=self.send_request(method,url,**arges_name["request"])
res_text=res.text
#状态码
res_status=res.status_code
res_json=""
try:
res_json = res.json()
except Exception as e:
print("jsonpath数据类型必须是json格式")
if "extract" in yaml_key:
for key,values in arges_name["extract"].items():
if "(.*?)" in values or "(.+?)" in values:
zz_value=re.search(values,res_text)
if zz_value:
write_token_yaml({key:zz_value.group(1)})
else:
jp_values=jsonpath.jsonpath(res_json,values)
if jp_values:
write_token_yaml({key:jp_values[0]})
# 断言方法,arges_name["validate"]为yaml文件中需要断言的所有值
# res_json 为接口返回的值
# res_status 为接口返回的状态码
self.assert_result(arges_name["validate"],res_json,res_status)
else:
print("request中缺少关键字段:name,request")
else:
print("yaml文件第一阶段缺少关键字段:name,request")
session=requests.session()
def send_request(self,method,url,**kwargs):
url = self.url + self.read_token(url)
for key,value in kwargs.items():
if key in ["params","json","data","headers"]:
kwargs[key]=self.read_token(value)
elif key == "files":
for file_key,file_value in value.items():
value[file_key] = open(file_value,"rb")
res=Unifiedrequest.session.request(method,url,**kwargs)
print(res.text)
return res
#断言
def assert_result(self,yq_result,sj_result,res_status):
flag_all = 0
# 循环得到yaml文件的数据列表
for yq in yq_result:
#循环输出字典中的键值对
for key,value in yq.items():
#如果键等于equals
if key == "equals":
flag = self.assert_equals(value,res_status,sj_result)
flag_all = flag_all+flag
elif key == "contains":
flag = self.assert_cintains(value,sj_result)
flag_all = flag_all+flag
else:
print("该断言还未添加,暂不支持")
assert flag_all == 0
#断言-等于
def assert_equals(self,value,res_status,sj_result):
flag = 0
for key,value in value.items():
#断言状态是否与预期一致
if key == "status_code":
if res_status != value:
flag = flag+1
print(f"断言失败,预期状态码{value}与返回状态码{res_status}不一致")
else:
assert_value=jsonpath.jsonpath(sj_result,f"$..{key}")
if assert_value:
if value not in assert_value:
flag = flag+1
print(f"断言失败,{key}不等于{value}")
else:
flag = flag+1
print(f"{key}不存在")
return flag
#断言_包含
def assert_cintains(self,value,sj_result):
flag = 0
if value not in str(sj_result):
flag=flag+1
print(f"断言失败{value}不存在{sj_result}中")
return flag