def save_response(cls, key: str, value: object) -> None: """ 保存实际响应 :param key: 保存字典中的key,一般使用用例编号 :param value: 保存字典中的value,使用json响应 """ cls.response_dict[key] = value logger.info(f'添加key: {key}, 对应value: {value}') allure_step('存储实际响应', cls.response_dict)
def handle_header(cls, header_str: str) -> dict: """处理header, 将用例中的表达式处理后 追加到基础header中 :header_str: 用例栏中的header return header: """ if header_str == '': header_str = '{}' cls.header.update(cls.handle_data(header_str)) allure_step('请求头', cls.header) return cls.header
def send_api( cls, url, method, parametric_key, header=None, data=None, file=None) -> dict: """ :param method: 请求方法 :param url: 请求url :param parametric_key: 入参关键字, params(查询参数类型,明文传输,一般在url?参数名=参数值), data(一般用于form表单类型参数) json(一般用于json类型请求参数) :param data: 参数数据,默认等于None :param file: 文件对象 :param header: 请求头 :return: 返回res对象 """ session = cls.get_session() if parametric_key == 'params': res = session.request( method=method, url=url, params=data, headers=header) elif parametric_key == 'data': res = session.request( method=method, url=url, data=data, files=file, headers=header) elif parametric_key == 'json': res = session.request( method=method, url=url, json=data, files=file, headers=header) else: raise ValueError( '可选关键字为params, json, data') response = res.json() logger.info( f'\n最终请求地址:{res.url}\n请求方法:{method}\n请求头:{header}\n请求参数:{data}\n上传文件:{file}\n响应数据:{response}') allure_step_no(f'响应耗时(s): {res.elapsed.total_seconds()}') allure_step('响应结果', response) return response
def assert_result(cls, response: dict, expect_str: str): """ 预期结果实际结果断言方法 :param response: 实际响应字典 :param expect_str: 预期响应内容,从excel中读取 return None """ expect_dict = convert_json(expect_str) index = 0 for k, v in expect_dict.items(): actual = extractor(response, k) index += 1 logger.info( f'第{index}个断言,实际结果:{actual} | 预期结果:{v} \n断言结果 {actual == v}') allure_step(f'第{index}个断言', f'实际结果:{actual} = 预期结果:{v}') assert actual == v
def handle_sql(cls, sql: str, db: object): """处理sql,并将结果写到响应字典中""" if sql not in ['no', '']: sql = rep_expr(sql, DataProcess.response_dict) else: sql = None allure_step('运行sql', sql) logger.info(sql) if sql is not None: # 查后置sql result = db.fetch_one(sql) allure_step('sql执行结果', {"sql_result": result}) logger.info(f'结果:{result}') if result is not None: # 将查询结果添加到响应字典里面,作用在,接口响应的内容某个字段 直接和数据库某个字段比对,在预期结果中 # 使用同样的语法提取即可 DataProcess.response_dict.update(result)
def handler_files(cls, file_obj: str) -> object: """file对象处理方法 :param file_obj: 上传文件使用,格式:接口中文件参数的名称:"文件路径地址"/["文件地址1", "文件地址2"] 实例- 单个文件: &file&D: """ if file_obj != '': for k, v in convert_json(file_obj).items(): # 多文件上传 if isinstance(v, list): files = [] for path in v: files.append((k, (open(path, 'rb')))) else: # 单文件上传 files = {k: open(v, 'rb')} allure_step('上传文件', file_obj) return files
def assert_result(cls, response: dict, expect_str: str): """ 预期结果实际结果断言方法 :param response: 实际响应结果 :param expect_str: 预期响应内容,从excel中读取 return None """ # 后置sql变量转换 expect_str = rep_expr(expect_str, DataProcess.response_dict) expect_dict = convert_json(expect_str) index = 0 for k, v in expect_dict.items(): # 获取需要断言的实际结果部分 actual = extractor(response, k) index += 1 logger.info( f'第{index}个断言,实际结果:{actual} | 预期结果:{v} \n断言结果 {actual == v}') allure_step(f'第{index}个断言', f'实际结果:{actual} = 预期结果:{v}') try: assert actual == v except AssertionError: raise AssertionError(f'断言失败 -|- 实际结果:{actual} || 预期结果: {v}')
def handle_sql(cls, sql: str, db: DB): """ 处理sql,如果sql执行的结果不会空,执行sql的结果和响应结果字典合并 :param sql: 支持单条或者多条sql,其中多条sql使用 ; 进行分割 多条sql,在用例中填写方式如下select * from user; select * from goods 每条sql语句之间需要使用 ; 来分割 单条sql,select * from user 或者 select * from user; :param db: 数据库连接对象 :return: """ sql = rep_expr(sql, DataProcess.response_dict) for sql in sql.split(";"): sql = sql.strip() if sql == '': continue # 查后置sql result = db.execute_sql(sql) allure_step(f'执行sql: {sql}', result) logger.info(f'执行sql: {sql} \n 结果: {result}') if result is not None: # 将查询结果添加到响应字典里面,作用在,接口响应的内容某个字段 直接和数据库某个字段比对,在预期结果中 # 使用同样的语法提取即可 DataProcess.response_dict.update(result)
class BaseRequest(object): session = None @classmethod def get_session(cls): if cls.session is None: cls.session = requests.Session() return cls.session @classmethod def send_request(cls, case: list, env: str = 'dev') -> object: """处理case数据,转换成可用数据发送请求 :param case: 读取出来的每一行用例内容,可进行解包 :param env: 环境名称 默认使用config.yaml server下的 dev 后面的基准地址 return: 响应结果, 预期结果 """ case_number, case_title, path, token, method, parametric_key, file_obj, data, sql, expect, is_save = case logger.debug( f"用例进行处理前数据: \n 接口路径: {path} \n 请求参数: {data} \n 后置sql: {sql} \n 预期结果: {expect} \n 保存响应: {is_save}" ) # allure报告 用例标题 allure_title(case_title) # 处理url、header、data、file、的前置方法 url = ReadFile.read_config( f'$.server.{env}') + DataProcess.handle_path(path) allure_step('请求地址', url) header = DataProcess.handle_header(token) allure_step('请求头', header) data = DataProcess.handle_data(data) allure_step('请求参数', data) file = DataProcess.handler_files(file_obj) allure_step('上传文件', file_obj) # 发送请求 res = cls.send_api(url, method, parametric_key, header, data, file) allure_step('响应耗时(s)', res.elapsed.total_seconds()) allure_step('响应内容', res.json()) # 响应后操作 if token == '写': DataProcess.have_token['Authorization'] = extractor( res.json(), ReadFile.read_config('$.expr.token')) allure_step('请求头中添加Token', DataProcess.have_token) # 保存用例的实际响应 if is_save == "是": DataProcess.save_response(case_number, res.json()) allure_step('存储实际响应', DataProcess.response_dict) return res.json(), expect, sql
class BaseRequest(object): session = None @classmethod def get_session(cls): """ 单例模式保证测试过程中使用的都是一个session对象 :return: """ if cls.session is None: cls.session = requests.Session() return cls.session @classmethod def send_request(cls, case: list, env: str = 'dev') -> object: """处理case数据,转换成可用数据发送请求 :param case: 读取出来的每一行用例内容,可进行解包 :param env: 环境名称 默认使用config.yaml server下的 dev 后面的基准地址 return: 响应结果, 预期结果 """ case_number, case_title, header, path, method, parametric_key, file_obj, data, sql, expect, is_save = case logger.debug( f"用例进行处理前数据: \n 接口路径: {path} \n 请求参数: {data} \n 后置sql: {sql} \n 预期结果: {expect} \n 保存响应: {is_save}") # allure报告 用例标题 allure_title(case_title) # 处理url、header、data、file、的前置方法 url = DataProcess.handle_path(path, env) header = DataProcess.handle_header(header) data = DataProcess.handle_data(data) allure_step('请求数据', data) file = DataProcess.handler_files(file_obj) # 发送请求 response = cls.send_api(url, method, parametric_key, header, data, file) # 保存用例的实际响应 if is_save == "是": DataProcess.save_response(case_number, response) return response, expect, sql