【第六章】二次封装断言 设计断言库
对断言模块进行二次封装
- 为什么要断言,为什么要二次封装
自动化测试框架中,断言这一部分是必不可少的,使用unittest自带的断言功能不太适合框架,且断言支持不强大(比如json断言、正则断言都不支持),所以在框架中把断言重新设计封装成check类。
具体设计思想:
- 设计excel用例信息时,添加期望结果类型(无、json键是否存在、正则匹配、json键值对)、期望结果两个字段
- 通过check类的方法实现断言后返回一个json数据,里面包含断言结果以及相应返回值
- check类返回的结果放入封装的get和post方法中,然后在多接口运行方法中把结果作为是否继续执行下一个接口的依据
- 返回最后的结果在unitest中获取到后,只需要统一使用assertTrue来进行断言即可
- 小试牛刀
代码示例: 对比键的单个、多个键是否存在
# -*- coding: utf-8 -*- # @Time : 2021/12/13 13:41 # @Author : Limusen # @File : assert_demo_09 """ 断言demo """ import json # 断言基础实现举例 str1 = '{"access_token":"12312jkssa"}' str2 = '{"access_token":"ACCESS_TOKEN","expires_in":7200}' # 转成json字典 json_obj = json.loads(str1) json_obj_02 = json.loads(str2) # 判断字典的键中是否跟 access_token 一样的 # 对比单个值 if "access_token" in json_obj.keys(): print(True) else: print(False) # 对比多个值 check_keys = ["access_token", "expires_in"] result_list = [] for check_key in check_keys: if check_key in json_obj_02.keys(): print("我是正确的") result_list.append(True) else: print("我是错误的") result_list.append(False) if False in result_list: print(False) print(result_list)
- 封装成类方法
- common模块新建check_utils.py
- 示例代码
- check_utils.py
# -*- coding: utf-8 -*- # @Time : 2021/12/13 14:07 # @Author : Limusen # @File : check_utils class CheckUtils: def __init__(self, response_data): """ :param response_data: 响应结果 """ self.response_data = response_data self.function = { "json_check": self.json_key_check, } def json_key_check(self, check_data): """ :param check_data: 需要检查的字段,注意得是字符串才行,因为要分割 :return: True说明断言成功,False说明断言失败 """ # 字符串逗号分割 key_list = check_data.split(",") tmp_result = [] # 取出需要断言的字段 for check_key in key_list: # 如果 check_key 在json串的键当中,则添加True,不是则添加False if check_key in self.response_data.json().keys(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: # 只要有一个不符合 用例全部失败 return False else: return True if __name__ == '__main__': import requests url = "https://api.weixin.qq.com/cgi-bin/token" get_params = {"grant_type": "client_credential", "appid": "wxb637f1f0d", "secret": "501123d2da9011d0f084"} response = requests.get(url=url, params=get_params) ck = CheckUtils(response) print(ck.json_key_check("access_token,expires_in"))
- 优化check_utils 继续增加可断言类型,新增运行断言方法的总控开关
# -*- coding: utf-8 -*- # @Time : 2021/12/13 14:07 # @Author : Limusen # @File : check_utils class CheckUtils: def __init__(self, response_data): """ :param response_data: 响应结果 """ self.response_data = response_data self.function = { "json_check": self.json_key_check } def json_key_check(self, check_data): """ :param check_data: 需要检查的字段,注意得是字符串才行,因为要分割 :return: True说明断言成功,False说明断言失败 """ # 字符串逗号分割 key_list = check_data.split(",") tmp_result = [] # 取出需要断言的字段 for check_key in key_list: # 如果 check_key 在json串的键当中,则添加True,不是则添加False if check_key in self.response_data.json().keys(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: # 只要有一个不符合 用例全部失败 return False else: return True def run_check(self, check_type, except_result): """ :param check_type: 检查的类型 :param except_result: 检查的字段 :return: """ return self.function[check_type](except_result) if __name__ == '__main__': import requests url = "https://api.weixin.qq.com/cgi-bin/token" get_params = {"grant_type": "client_credential", "appid": "wxb637f897f0bf1f0d", "secret": "501123d2d367b109a5cb9a9011d0f084"} response = requests.get(url=url, params=get_params) ck = CheckUtils(response) # print(ck.json_key_check("access_token,expires_in")) print(ck.run_check('json_check', 'access_token,expires_in'))
- 新增其他类型断言
- assert_demo_10.py
# -*- coding: utf-8 -*- # @Time : 2021/12/13 13:41 # @Author : Limusen # @File : assert_demo_10 """ 断言demo 对比json数据 """ import json # 单项对比 # key — value 断言基础实现举例 str1 = '{"access_token":"ACCESS_TOKEN","expires_in":7200}' except_str = '{"expires_in": 7200}' json_obj = json.loads(str1) except_obj = json.loads(except_str) # print(json_obj.items()) # print(except_obj.items()) # 示例2: a = [(1, 2)] b = [(2, 3), (1, 2)] e = [] for c in b: if c == a[0]: e.append(True) else: e.append(False) if False in e: print(False) print(list(except_obj.items())[0]) print(json_obj.items()) # 如果expires_in 在 json_obj列表中则输出ture if list(except_obj.items())[0] in json_obj.items(): print(True) else: print(False) # 多项对比 str1 = '{"access_token":"ACCESS_TOKEN","expires_in":7200}' except_str_02 = '{"expires_in": 7200,"access_token":"ACCESS_TOKEN"}' json_obj_02 = json.loads(str1) except_obj_02 = json.loads(except_str_02) yes_no = [] for except_res in except_obj_02.items(): if except_res in json_obj_02.items(): yes_no.append(True) else: yes_no.append(False) if False in yes_no: print(False)
- 封装至check_utils.py
- key_value_check
# -*- coding: utf-8 -*- # @Time : 2021/12/13 14:07 # @Author : Limusen # @File : check_utils import json class CheckUtils: def __init__(self, response_data): """ :param response_data: 响应结果 """ self.response_data = response_data self.function = { "json_key": self.key_check, "json_key_value": self.key_value_check } def key_check(self, check_data): """ 检查键是否相同 :param check_data: 需要检查的字段,注意得是字符串才行,因为要分割 :return: True说明断言成功,False说明断言失败 """ # 字符串逗号分割 key_list = check_data.split(",") tmp_result = [] # 取出需要断言的字段 for check_key in key_list: # 如果 check_key 在json串的键当中,则添加True,不是则添加False if check_key in self.response_data.json().keys(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: # 只要有一个不符合 用例全部失败 return False else: return True def key_value_check(self, check_data): """ 检查键值对是否一致 :param check_data: :return: """ key_dict = json.loads(check_data) tmp_result = [] for check_key in key_dict.items(): if check_key in self.response_data.json().items(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: return False else: return True def run_check(self, check_type, except_result): """ :param check_type: 检查的类型 :param except_result: 检查的字段 :return: """ return self.function[check_type](except_result) if __name__ == '__main__': import requests url = "https://api.weixin.qq.com/cgi-bin/token" get_params = {"grant_type": "client_credential", "appid": "wxb637f897f0bf1f0d", "secret": "501123d2d367b109a5cb9a9011d0f084"} response = requests.get(url=url, params=get_params) ck = CheckUtils(response) print(ck.run_check('json_key', "access_token,expires_in")) print(ck.run_check('json_key_value', '{"expires_in": 7200}'))
- 全部封装代码
check_utils.py
# -*- coding: utf-8 -*- # @Time : 2021/12/13 14:07 # @Author : Limusen # @File : check_utils import json import re class CheckUtils: def __init__(self, response_data): """ :param response_data: 响应结果 """ self.response_data = response_data self.function = { "none_check": self.none_check(), "json_key": self.key_check, "json_key_value": self.key_value_check, "body_regexp": self.body_regexp_check, "header_key_check": self.header_key_check, "header_key_value_check": self.header_key_value_check, "response_code_check": self.response_code_check } def none_check(self): """ 断言类型为空的情况 :return: """ return True def key_check(self, check_data): """ 检查键是否相同 :param check_data: 需要检查的字段,注意得是字符串才行,因为要分割 :return: True说明断言成功,False说明断言失败 """ # 字符串逗号分割 key_list = check_data.split(",") tmp_result = [] # 取出需要断言的字段 for check_key in key_list: # 如果 check_key 在json串的键当中,则添加True,不是则添加False if check_key in self.response_data.json().keys(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: # 只要有一个不符合 用例全部失败 return False else: return True def key_value_check(self, check_data): """ 检查键值对是否一致 :param check_data: :return: """ key_dict = json.loads(check_data) tmp_result = [] for check_key in key_dict.items(): if check_key in self.response_data.json().items(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: return False else: return True def body_regexp_check(self, check_data): """ 根据正则表达式断言 :param check_data: :return: """ if re.findall(check_data, self.response_data.text): # 能找到check_data的值则算通过 return True else: return False def header_key_check(self, check_data): """ 检查头部信息是否包含某个值 可以参照key_check() :param check_data: :return: """ # 字符串逗号分割 key_list = check_data.split(",") tmp_result = [] # 取出需要断言的字段 for check_key in key_list: # 如果 check_key 在json串的键当中,则添加True,不是则添加False if check_key in self.response_data.headers.keys(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: # 只要有一个不符合 用例全部失败 return False else: return True def header_key_value_check(self, check_data): """ 检查头部键值对是否一致 参照key_value_check() :param check_data: :return: """ key_dict = json.loads(check_data) tmp_result = [] for check_key in key_dict.items(): if check_key in self.response_data.headers.items(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: return False else: return True def response_code_check(self, check_data): """ 检查返回状态码 :param check_data: :return: """ if self.response_data.status_code == int(check_data): return True else: return False def run_check(self, check_type, except_result): """ :param check_type: 检查的类型 :param except_result: 检查的字段 :return: """ return self.function[check_type](except_result) if __name__ == '__main__': import requests url = "https://api.weixin.qq.com/cgi-bin/token" get_params = {"grant_type": "client_credential", "appid": "wxb637f897f0bf1f0d", "secret": "501123d2d367b109a5cb9a9011d0f084"} response = requests.get(url=url, params=get_params) # print(response.headers) ck = CheckUtils(response) print(ck.none_check()) print(ck.run_check('json_key', "access_token,expires_in")) print(ck.run_check('json_key_value', '{"expires_in": 7200}')) print(ck.run_check("body_regexp", '"access_token":"(.+?)"')) print(ck.run_check("header_key_check", "Connection")) print(ck.run_check("header_key_value_check", '{"Connection": "keep-alive"}')) print(ck.run_check("response_code_check", "200"))
- 这里调用ck.run_check('none_check'),会报错 ,优化一下代码
def run_check(self, check_type, except_result): """ :param check_type: 检查的类型 :param except_result: 检查的字段 :return: """ if check_type == "none" or except_result == "": return self.function["none"]() else: return self.function[check_type](except_result)
- 整体代码
# -*- coding: utf-8 -*- # @Time : 2021/12/13 14:07 # @Author : Limusen # @File : check_utils import json import re class CheckUtils: def __init__(self, response_data): """ :param response_data: 响应结果 """ self.response_data = response_data self.function = { "none": self.none_check(), "json_key": self.key_check, "json_key_value": self.key_value_check, "body_regexp": self.body_regexp_check, "header_key_check": self.header_key_check, "header_key_value_check": self.header_key_value_check, "response_code_check": self.response_code_check } def none_check(self): """ 断言类型为空的情况 :return: """ return True def key_check(self, check_data): """ 检查键是否相同 :param check_data: 需要检查的字段,注意得是字符串才行,因为要分割 :return: True说明断言成功,False说明断言失败 """ # 字符串逗号分割 key_list = check_data.split(",") tmp_result = [] # 取出需要断言的字段 for check_key in key_list: # 如果 check_key 在json串的键当中,则添加True,不是则添加False if check_key in self.response_data.json().keys(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: # 只要有一个不符合 用例全部失败 return False else: return True def key_value_check(self, check_data): """ 检查键值对是否一致 :param check_data: :return: """ key_dict = json.loads(check_data) tmp_result = [] for check_key in key_dict.items(): if check_key in self.response_data.json().items(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: return False else: return True def body_regexp_check(self, check_data): """ 根据正则表达式断言 :param check_data: :return: """ if re.findall(check_data, self.response_data.text): # 能找到check_data的值则算通过 return True else: return False def header_key_check(self, check_data): """ 检查头部信息是否包含某个值 可以参照key_check() :param check_data: :return: """ # 字符串逗号分割 key_list = check_data.split(",") tmp_result = [] # 取出需要断言的字段 for check_key in key_list: # 如果 check_key 在json串的键当中,则添加True,不是则添加False if check_key in self.response_data.headers.keys(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: # 只要有一个不符合 用例全部失败 return False else: return True def header_key_value_check(self, check_data): """ 检查头部键值对是否一致 参照key_value_check() :param check_data: :return: """ key_dict = json.loads(check_data) tmp_result = [] for check_key in key_dict.items(): if check_key in self.response_data.headers.items(): tmp_result.append(True) else: tmp_result.append(False) if False in tmp_result: return False else: return True def response_code_check(self, check_data): """ 检查返回状态码 :param check_data: :return: """ if self.response_data.status_code == int(check_data): return True else: return False def run_check(self, check_type, except_result): """ :param check_type: 检查的类型 :param except_result: 检查的字段 :return: """ if check_type == "none" or except_result == "": return self.function["none"]() else: return self.function[check_type](except_result) if __name__ == '__main__': import requests url = "https://api.weixin.qq.com/cgi-bin/token" get_params = {"grant_type": "client_credential", "appid": "wxb637f897f0bf1f0d", "secret": "501123d2d367b109a5cb9a9011d0f084"} response = requests.get(url=url, params=get_params) # print(response.headers) ck = CheckUtils(response) print(ck.none_check()) print(ck.run_check('json_key', "access_token,expires_in")) print(ck.run_check('json_key_value', '{"expires_in": 7200}')) print(ck.run_check("body_regexp", '"access_token":"(.+?)"')) print(ck.run_check("header_key_check", "Connection")) print(ck.run_check("header_key_value_check", '{"Connection": "keep-alive"}')) print(ck.run_check("response_code_check", "200"))
这一章将的是断言库的封装,下一章将讲解将断言库整合到request中