思路
创建测试用例表,准备数据--读取测试用例表中的数据--获取接口返回的数据进行比较--将结果写入数据表
根据这个思路构造名为compare_param的类,类中包含了三个方法:
(1)compare_json_code(self,case_data,result_data): 当接口返回结果是json格式的数据,通过这个方法获取数据表中待比较code值与接口返回的状态码resultCode对比,并将结果写回数据库
(2)def compare_json_params(self,case_data,result_data): 当接口返回结果是json格式的数据,通过这个方法获取数据表中接口比较参数集合params_to_compare与接口返回的参数对比,并将结果写入数据库中
(3) def jsondata_to_set(self,dict_ob, set_ob): 将json格式的数据进行去重操作
创建测试用例表case_interface
CREATE TABLE `case_interface` (
`id` int(2) NOT NULL AUTO_INCREMENT,
`name_interface` varchar(128) NOT NULL COMMENT '接口名称',
`exe_level` int(2) DEFAULT NULL COMMENT '执行优先级,0代表BVT',
`exe_mode` varchar(4) DEFAULT NULL COMMENT '执行方式:post,get,默认是post方式',
`url_interface` varchar(128) DEFAULT NULL COMMENT '接口地址:如果以http开头的则直接使用改地址,否则拼接上不同环境的ip前缀作为接口地址',
`header_interface` text COMMENT '接口请求的头文件,有则使用,无则调用配置文件',
`params_interface` varchar(256) DEFAULT NULL COMMENT '接口请求的参数',
`result_interface` text COMMENT '接口返回结果',
`code_to_compare` varchar(16) DEFAULT NULL COMMENT '待比较的code值,用户自定义比较值,例如returncode和code等,默认returncode',
`code_actual` varchar(16) DEFAULT NULL COMMENT '接口实际code实际返回值',
`code_expect` varchar(16) DEFAULT NULL COMMENT '接口预期code返回值',
`result_code_compare` int(2) DEFAULT NULL COMMENT 'code比较结果,0-pass,1-fail,2-无待比较参数,3-比较出错,4-返回包不合法,5-系统异常'
`params_to_compare` varchar(256) DEFAULT NULL COMMENT '接口比较参数集合,用于比较参数完整性',
`params_actual` text COMMENT '接口实际返回参数',
`result_params_compare` int(2) DEFAULT NULL COMMENT 'code比较结果,0-pass,1-fail,2-获取参数集错误:去重错误,5-系统异常',
`case_status` int(2) DEFAULT '0' COMMENT '用例状态 0-有效,1-无效',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='接口用例表';
关键字参数:验证结构体是否正确,http返回包是否有对应关键字,返回有关键字参数的情况下去比较关键字参数的值和实际结果是否相等
参数完整性:预期参数列表都在实际返回列表中,集合的包含关系issubset()
python操作MySQL返回数据
python操作Mysql一般返回两种数据,元祖和字典。此处要用到是字典类型的数据
import pymysql,re,logging,os
class OperationDb_interface(object):
def __init__(self):
self.conn=pymysql.connect(host='localhost',
user='root',
passwd='*****',
db='my_test',
port=3306,
charset='utf8',
cursorclass=pymysql.cursors.DictCursor#返回字典
)#创建数据库链接
self.cur=self.conn.cursor()#创建游标
在默认情况下cursor方法返回的是BaseCursor类型对象,BaseCursor类型对象在执行查询后每条记录的结果以列表(list)表示。如果要返回字典(dict)表示的记录,就要设置cursorclass参数为pymysql.cursors.DictCursor类
代码
#-*- coding:utf-8 -*-
#__author__='yy'
'''
@desc:根据case_interface 表中的信息对response结果做断言(code,参数完整性)操作,将断言结果写入数据表中
question:接口返回对象不是json,如xml,所以我们这个类应该具有可扩展性
'''
from mylogging import mylogger
from Interface import OperationDb_interface
import json
class compare_param:
def compare_json_code(self,case_data,result_data):
'''
当接口返回json格式数据,通过这个方法,对比返回状态码code,将结果写回数据库
:param case_data: 数据库中存储测试case的数据,一条数据(字典类型)
:param result_data:调用接口返回json格式的数据
:return:
1.{`code`:200,`message`:`code相等`,`content`:``}
2.{`code`:300,`message`:`code不相等`,`content`:``}
3.{`code`:301,`message`:`code不存在`,`content`:``}
4.{`code`:400,`message`:`code比较出现异常`,`content`:``}
'''
try:
op_sql= OperationDb_interface()
update_sql="UPDATE case_interface SET result_interface=%s,code_actual=%s,result_code_compare=%s WHERE id =%s"
code_expected = case_data.get("code_to_compare")#获取数据表中保存的code值
if 'resultCode' in result_data:
result_code = result_data.get("resultCode") #获取返回结果中的code值
if code_expected == result_code:
op_sql.op_sql(update_sql,(str(result_data),result_code,0,case_data.get("id"))) #code比较结果,0-pass
result={'code':200,'message':'code相等','content':''}
else:
op_sql.op_sql(update_sql,(str(result_data),result_code,1,case_data.get("id")))
result = {'code':300,'message':'code不相等','content':''}
else:
op_sql.op_sql(update_sql,(str(result_data),None,2,case_data.get("id")))#2-无待比较参数
result = {'code':301,'message':'code不存在','content':''}
except BaseException as e:
op_sql.op_sql(update_sql,(str(result_data),None,4,case_data.get("id")))#4-比较异常
mylogger.info("[compare_json_code 测试用例信息]-%s"%str(case_data))
mylogger.info("[compare_json_code 接口返回的信息]-%s"%str(result_data))
mylogger.exception(e)
result={'code':400,'message':'code比较出现异常','content':''}
return result
def jsondata_to_set(self,dict_ob,set_ob):
'''
json格式数据去重操作:递归
:param dict_ob: dict:json格式数据
:param set_ob: 传入set对象(没有内容)
:return:
1.{"code":200,"message":"json:参数去重成功","content":set_ob}
2.{"code":400,"message":"json:参数去重出现异常","content":""}
'''
try:
for key,value in dict_ob.items():
set_ob.add(key)
if isinstance(value,dict):
self.jsondata_to_set(value,set_ob)
elif isinstance(value,list):
for li in value:
self.jsondata_to_set(li,set_ob)
result = {"code":200,"message":"json:参数去重成功","content":set_ob}
except BaseException as e:
mylogger.info("[jsondata_to_set params]-(dict_ob:%s,set_ob:%s)"%(str(dict_ob),str(set_ob)))
mylogger.exception(e)
result = {"code":400,"message":"json:参数去重出现异常","content":""}
return result
def compare_json_params(self,case_data,result_data):
'''
当借口返回结果是json格式的数据,通过这个方法,可以对比返回参数和数据库中的预期参数,并将结果写入数据库中
:param case_data:数据库返回的用例信息,dict=>一条数据
:param result_data:接口返回json数据,dict
:return:
1.{"code":200,"message":"参数完整性相等","content":""}
2.{"code":301,"message":"参数完整性不相等","contenr":""}
3.{"code":300,"message":"去重失败:获取参数集错误","content":""}
4.{"code":400,"message":"参数完整性比较出现异常","content":""}
'''
try:
op_sql = OperationDb_interface()
#获取预期参数
case_params =case_data.get("params_to_compare")
case_params_set = eval(case_params) #将字符串str当成有效的表达式来求值并返回计算结果
#更新数据的sql语句
update_sql="UPDATE case_interface set params_actual=%s ,result_params_compare=%s WHERE id=%s"
#对json数据进行去重操作
params_set = set() #set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等
set_result = self.jsondata_to_set(result_data,params_set)
print(case_params_set)
print(params_set)
if set_result.get("code")==200:
#判断是否包含
if case_params_set.issubset(params_set):#如果集合case_params_set中每个元素都在params_set中
#更新数据表
op_sql.op_sql(update_sql,(str(params_set),0,case_data.get("id"))) #0 pass
result = {"code":200,"message":"参数完整性相等","content":""}
else:
op_sql.op_sql(update_sql,(str(params_set),1,case_data.get("id"))) #1 fail
result={"code":301,"message":"参数完整性不相等","content":""}
elif set_result.get("code")==400:
op_sql.op_sql(update_sql,(None,2,case_data.get("id")))# 2 去重错误
result = {"code":300,"message":"去重失败:获取参数集错误","conten":""}
except BaseException as e:
op_sql.op_sql(update_sql,(None,5,case_data.get("id"))) # 5 系统异常
mylogger.info("[compare_json_params params - (case_data:%s,result_data:%s)]"%(str(case_data),str(result_data)))
mylogger.exception(e)
result = {"code":400,"message":"参数完整性比较出现异常","content":""}
return result
if __name__ == "__main__":
#获取数据库的测试用例信息
mysql_op = OperationDb_interface()
case_data = mysql_op.selectOne("select * from case_interface WHERE id=1")
#创建一个compare对象
cmp_obj =compare_param()
'''
#code比较
#test_compare_json_code:200-code相等
result_interface= '{"message": "获取附近服务商成功","nextPage": 1,"pageNo": 0,"merchantInfos11":"测试环境店铺","resultCode":"000","totalPage": 66746}'
cmpare_result = cmp_obj.compare_json_code(case_data,json.loads(result_interface))
print(cmpare_result)
'''
'''
result_interface = '{"message": "获取附近服务商成功","nextPage": 1,"pageNo": 0,"merchantInfos": [{"phone": "15100000000","star": 5,"totalQualityEvaluation": 0,"photoUrls": "","latitude": 0},{"phone": "15200000000","detail": null,"sex": null,"serviceFrequency": 0}],"resultCode": "000","totalPage": 66746}'
my_set = set()
result = cmp_obj.jsondata_to_set(json.loads(result_interface), my_set)
if result.get("code") == 200:
print(result.get("code"))
print(result.get("message"))
print(result.get("content"))
'''
#参数完整性的比较
result_interface = '{"message": "获取附近服务商成功","nextPage": 1,"pageNo": 0,"merchantInfos":"测试环境店铺","resultCode": "000","totalPage": 66746}'
cmpare_result = cmp_obj.compare_json_params(case_data,json.loads(result_interface))
print(cmpare_result)
备注
json.loads
用法:把json格式字符串解码转换成python对象字典(json与字典的不同对于参数引号的使用,json使用双引号,字典使用单引号,而python只能处理单引号)
ex:str_json='{"message":"success","page":1,"totalPage":100}'
dict_json=json.loads(str_json)
结果:{u'message':u'success',u'totalPage':100,u'page':1}dict.has_key(key)与dict.iteritems()
dict.has_key(key): 判断键名key是不是在字典dict中,如果键在字典dict里返回true,否则返回false
ex:test_dict={'message':'success','totalPage':100,'page':1}
print test_dict.has_key('message')
True
print test_dict.has_key(‘project’)
False
dict.iteritems(): 返回字典键、值的迭代器,一般用于循环获取键和值
ex:test_dict={'message':'success','totalPage':100,'page':1}
print test_dict.iteritems()
for key,value in test_dict,iteritems():
print (key,value)
message success
total Page 100
page 1
- eval()与 instance()
eval():将字符串str当成有效的python表达式来求值并返回计算结果,这里将str类型的文件转换为本来面目(list、tuple、dict和string之间的转换)
ex:u_str='{"message":"success","page":1,"totalPage":100}'
print (eval(str_json))
{'page': 1, 'message': 'success', 'totalPage': 100}
isinstance(value,(dict,list)): 格式判断,指value的类型属于dict和list中的一种,如果是则返回True,否则返回False
ex:test_dict={"message":"success","page":1,"totalPage":100}
print (isinstance(test_dict,(dict,list)))
True
print (isinstance('python',(dict,list)))
False
- set() 与issubset()
set(): 集合也是python的一种数据类型,它和列表很像,但是集合的数据是有序的且不能重复。所以我们可以将列表转换成集合,使用的就是set()
ex:test_list=[1,2,3,3,4,2]
t=set(test_list)
print(t)
{1, 2, 3, 4}
issubset(): 集合的包含关系,如s.issubset(t),指的是否s中的每个元素都在t中,是则返回True,否则返回False
ex:a=set([1,2,3,4,5,])
b=set([1,2,3])
print (a.issubset(b))
False
print (b.issubset(a))
True
跟着亭子青年学习接口测试