def __init__(self, ): #获取图片接口 self.url = 'https://' + config.longinfo["url"] + '/sign/imageCode' self.headers = {"Content-Type": "application/json;charset=UTF-8"} self.session = requests.session() self.log = MyLog() if os.path.exists(config.imagepath) is False: os.makedirs(config.imagepath) self.picpath = os.path.join(config.imagepath, 'vcode.png')
class GetVcode: def __init__(self, ): #获取图片接口 self.url = 'https://' + config.longinfo["url"] + '/sign/imageCode' self.headers = {"Content-Type": "application/json;charset=UTF-8"} self.session = requests.session() self.log = MyLog() if os.path.exists(config.imagepath) is False: os.makedirs(config.imagepath) self.picpath = os.path.join(config.imagepath, 'vcode.png') def _write_imge(self, img_base_str): # 将图片写入文件 img = base64.b64decode(img_base_str) # 得到图片 file = open(self.picpath, 'wb') file.write(img) file.close() #解码BASE64加密图片 def get_imageId(self): response = self.session.get(url=self.url, verify=False).json() image = response.get("data").get("image") img_base64 = re.findall(r'data:image/png;base64,(.*)', image)[0] self._write_imge(img_base64) imageId = response.get("data").get("imageId") return imageId def _get_new_img(self): oriimage = Image.open(self.picpath) #对图片转化为灰度图像 img = oriimage.convert('L') img.save(self.picpath) i = open(self.picpath, 'rb') final_img = i.read() return final_img #获取验证码 def get_vcode(self): # picfile:图片文件名 # 百度提供 """ 你的 APPID AK SK """ # 应用的appid APP_ID = '22532565' # 应用的appkey API_KEY = 'fCvsC8UOdrLFPDGFPpQW0X1I' # 应用的secretkey SECRET_KEY = 'oMnORbkMcdnTnEm2XNPzls08jOxGEGkx' client = AipOcr(APP_ID, API_KEY, SECRET_KEY) """ 调用通用文字识别(高精度版) """ imageId = self.get_imageId() final_img = self._get_new_img() message = client.basicAccurate(final_img) try: vcode = message.get('words_result')[0].get('words') return vcode, imageId except Exception as e: self.log.debug("未获取到有效验证码{}:{}".format(message, e))
class Constructdata: def __init__(self): self.logs = MyLog() def _proc_body(self, data): #处理有模板替换的body if data: body = {} # body = {k: FuncReplace(v).reflex_variable() for k, v in (dict(data)).items()} for k, v in (dict(data)).items(): if isinstance(v, list): v[0] = int(FuncReplace( v[0]).reflex_variable()) #这里是为了处理groupids被模板替换后成了一个字符型 body[k] = v else: body[k] = FuncReplace(v).reflex_variable() else: body = data return body def proc_data(self, request_data): """ 处理request请求数据, :request_data: 经过get_case_obj_by_name处理过的数据 :return: 返加用于request请求的数据 """ #处理请求体,替换换要执行函数的内容 request_data = AttrDict(request_data) self.logs.debug("请求转入url{}".format(request_data.url)) try: params = self._proc_body(request_data.params) data = self._proc_body(request_data.data) json = self._proc_body(request_data.json) except AttributeError as e: self.logs.error("yaml文件内无此参数值,请检查".format(e)) #封装rquest数据 d = { "method": request_data.method.upper(), "url": "http://" + config.host + request_data.url, "params": params, "data": data, "json": json, "files": request_data.files, "headers": request_data.headers, "timeout": request_data.timeout, "verify": False } return d
def login(): """登录获取token等信息""" #urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) log = MyLog() req_data = {} longinfo = AttrDict(config.longinfo) url = 'https://' + longinfo.url + "/sign/login" req_data["account"] = '610f73a314e055b4c716058a4cdb09fc' req_data["password"] = '******' imageCode, imageId = GetVcode().get_vcode() headers = {"Conten-Type": "application/json;charset=UTF-8"} while True: while imageCode is None or len(imageCode) < 4: imageCode, imageId = GetVcode().get_vcode() else: req_data['imageCode'] = imageCode req_data["imageId"] = imageId response = requests.post(url=url, json=req_data, headers=headers, verify=False) data = response.json() if data["success"]: token = "DRCC " + response.json().get("data").get("token") print(token) return token break else: imageCode, imageId = GetVcode().get_vcode()
def __init__(self, yaml_path, rep_dict=None): """ :param yaml_path: yaml_case文件路径 """ try: self.source_data = HadnlerYaml.read_yaml_file( yaml_path) #获取yaml原始数据 if rep_dict: self.yaml_data = AttrDict( HadnlerYaml.replace_yaml_value( self.source_data, rep_dict)) #如果rep_dict不为空,则替换 else: self.yaml_data = AttrDict(self.source_data) self.test_info = AttrDict(self.yaml_data.testinfo) self.logs = MyLog() except Exception as a: self.logs.error("用例参数错误{}".format(a)) raise CaseParamsError
def login(): """登录获取token等信息""" #urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) log = MyLog() req_data = {} loginfo = AttrDict(config.longinfo) url = 'https://' + loginfo.url req_data["account"] = AESEncrypt(loginfo.username) req_data["password"] = AESEncrypt(loginfo.pwd) import jpype if not jpype.isJVMStarted(): jpype.shutdownJVM() imageCode, imageId = GetVcode().get_vcode() headers = {"Conten-Type": "application/json;charset=UTF-8"} while True: while imageCode is None or len(imageCode) < 4: imageCode, imageId = GetVcode().get_vcode() else: req_data['imageCode'] = imageCode req_data["imageId"] = imageId response = requests.post(url=url + "/sign/login", json=req_data, headers=headers, verify=False) data = response.json() if data["success"]: ssotoken = response.json().get("data").get("token") #appId重新激活应用时,会变,要修改 params = {"appId": "mc377723", "token": ssotoken} res = requests.get(url=url + "/app/redirection?", params=params, headers=headers, verify=False, allow_redirects=False) token = res.headers.get("location").split("token=")[1] print(token) return token break else: imageCode, imageId = GetVcode().get_vcode()
def __init__(self, except_dict, response): self.asserts_dict = except_dict self.response = response self.assert_type = ['body', 'headers', 'http_code'] self.log = MyLog()
class AssertActions(object): """断言处理器""" def __init__(self, except_dict, response): self.asserts_dict = except_dict self.response = response self.assert_type = ['body', 'headers', 'http_code'] self.log = MyLog() def assert_parse(self): pass def body_assert_parse(self, key): """ 拿到断言字典的key,取response相应的值 :param key: :return: response字典 """ body_rule = key.split('.') body_data = self._format_response_body() if len(body_rule) == 1: #如果不取body的子值,直接返回整个body return body_data try: json.dumps(body_data) #将返回值转为dict,如果无法转,报错 except (ValueError, TypeError): raise ResponseNotJson for rule in body_rule[1:]: section = re.findall(r"\[(.*)\]$", rule, re.I | re.M) #取索引下标[0]等 if len(section) == 0: #如果没有索引,直接返回respones["result"] body_data = body_data[rule] elif len(section ) == 1: #如果有,再按"[",切分,取response["result"],然后再返回 result[0] rule_new = rule.split('[')[0] body_data = body_data[rule_new] try: s = int(section[0]) body_data = body_data[s] except ValueError: raise CaseAssertNotSport return body_data def headers_assert_parse(self, key): headers_rule = key.split('.') if len(headers_rule) == 2: return self._format_response_headers()[headers_rule[-1]] else: raise CaseAssertNotSport def http_code_assert_parse(self, key): key_rule = key.split('.') if len(key_rule) == 1 and key_rule[0] == 'http_code': return self.response.status_code else: raise CaseAssertNotSport #TODO 加入数据库状态断言 def exec_assert(self): for k, v in self.asserts_dict.items(): self.log.debug('断言对象:{}'.format(k)) mod = k.split('.')[0] if mod not in self.assert_type: raise CaseAssertNotSport if mod == 'body': k_str = self.body_assert_parse(k) elif mod == 'headers': k_str = self.headers_assert_parse(k) elif mod == 'http_code': k_str = self.http_code_assert_parse(k) self.log.debug('断言对象取值:{}'.format(k_str)) v_str = FuncReplace(v).reflex_variable() self.log.debug('期望取值:{}'.format(v_str)) if isinstance(v_str, dict): self._compare_dict_assert(v_str, k_str) else: try: assert k_str == v_str except AssertionError: raise CaseAssertFailed('断言失败:实际值{} != 期望值{}'.format( k_str, v_str)) def _format_response_body(self): try: content = self.response.json() except (TypeError, ValueError): content = self.response.content.decode("utf-8") return content def _format_response_headers(self): return self.response.headers def _compare_dict_assert(self, except_dict, response_dict): """ 如果断言和返回都是字典,比较字典内所有的值 :param except_dict: :param response_dict: :return: """ flag = True k_list = set(response_dict.keys()) #实际结果的key集合 for k, v in except_dict.items(): if k in k_list: self.log.debug("resopnse boby断言key为:{},实际值为:{},期望值为:{}".format( k, v, response_dict.get(k))) if v != response_dict.get(k): flag = False try: assert flag except AssertionError: raise CaseAssertFailed('断言失败:实际值{} != 期望值{}'.format( except_dict, response_dict))
class CaseYamlParser: """ 用例数据解析器 """ def __init__(self, yaml_path, rep_dict=None): """ :param yaml_path: yaml_case文件路径 """ try: self.source_data = HadnlerYaml.read_yaml_file( yaml_path) #获取yaml原始数据 if rep_dict: self.yaml_data = AttrDict( HadnlerYaml.replace_yaml_value( self.source_data, rep_dict)) #如果rep_dict不为空,则替换 else: self.yaml_data = AttrDict(self.source_data) self.test_info = AttrDict(self.yaml_data.testinfo) self.logs = MyLog() except Exception as a: self.logs.error("用例参数错误{}".format(a)) raise CaseParamsError @property def test_suite(self): """获取测试套件名称""" return self.test_info.case_suite @property def suite_desc(self): """获取套件描述""" return self.test_info.descrpiton @property def get_rep_value(self): """获取替换字典""" return self.test_info.rep_value @property def case_module_class(self): """获取测试用例名称""" return self.test_info.module_class @property def get_premise(self): return self.yaml_data.premise #列表 @property def case_set_up(self): """获取前置条件方法""" return self.yaml_data.set_up @property def case_tear_down(self): """执行后置方法""" return self.yaml_data.tear_down #主要是后置删除接口调用 @property def get_all_case(self): """获取用例""" return self.yaml_data.test_case def get_case_obj_by_name(self, case_data_list, story_name): """ 获取用例数据 :param data: 传入yaml文件内的test_case数据,是个列表 :param story_name: 传入的测试函数名称 :return: 返回经过字典属性化的名称与story_name一致的用例数据 """ storys = [] if case_data_list: for case in case_data_list: case_name = case.get('test_name') #从所有用例数据内根据传入的用例名称运行测试用例,此处 if case_name and case_name == story_name: storys.append(case) if len(storys) == 0: raise CaseStoryNotFound if len(storys) > 1: raise CaseStoryRepeat return storys[0]
def __init__(self, text): self.text = text self.logs = MyLog()
def __init__(self): self.logs = MyLog()
# -*- coding:utf-8 -*- ''' @Time : 2021/3/9 11:01 @Author : 测试工程师Jane @FileName : dbopration.py @Description: ''' import pymysql import config from common.logs import MyLog log = MyLog() def conn_db(): conninfo = config.proc_mysqldb_info try: conn = pymysql.connect(**conninfo) log.info("数据库连接成功") return conn except Exception as e: log.error("连接失败,失败原因为{}".format(e)) #TODO 优化方法 def query_db(sql): """ 查询数据库 :param sqlinfo:sql :return: 查询元组