def makeCaseList(self,fileName,defNameHead): try: # 创建caseList文件 write_file('w',caseListFilePath,caseListName,'') with open(fileName,'r') as file: while 1: # 去除每行头部的空格或制表符 f = file.readline().strip().strip('/t') # 检查是否以class为开头 if f == None or f == u'\n' or f == u'' and f == u'\r\n': break if f.startwith('class'): classNameBeg = 5 classNameEnd = f.find('(',1) className = f[classNameBeg,classNameEnd] self.testCaseCount[className] = 0 elif 'className'in vars() and f.startwith('def'): defNameBeg = 3 defNameEnd = f.find('(',1) defName = f[defNameBeg,defNameEnd] # 过滤函数名 if defName.startwith(defNameHead): self.testCaseCount[className] += 1 writeData = className + '/' + defName write_file('a',caseListFilePath,caseListName,writeData) self.pyCaseFileCount += 1 logger.info('获取 test case 列表结束') except Exception as e: logger.error('获取 test case 列表时异常 %s'%(e)) return {'result':1,'msg':'获取 test case 列表时异常 %s'%(e)} return {'result':0,'msg':'获取 test case 列表结束','testCaseCount':self.testCaseCount}
def __init__(self, file_path=None): """ os.path.abspath('.')表示获取当前文件所在目录;os.path.dirname表示获取文件所在父目录;所以整个就是项目的所在路径 :param file_path:yaml文件路径,填写相对路径 """ root_dir = ReadConfig.proDir self.file_path = root_dir.replace('\\', '/') + file_path # self.file_path = os.path.join(root_dir, file_path) try: with open(self.file_path, 'r', encoding='utf-8') as f: self.yml = yaml.safe_load(f) except FileNotFoundError: logger.error(f"找不到文件{self.file_path}")
def get_dataparamsvalue(self, caseno=None): """ 获得yaml文件中的单个用例data中参数化的需要传入的实际值 :param caseno:用例编号 """ try: d = self.yml[caseno] try: return d['dataparamsvalue'] except KeyError: logger.warning(f"当前数据:{self.yml} 中找不到dataparamsvalue!!!") return None except KeyError: logger.error(f"当前数据:{self.yml} 中找不到{caseno}!!!") return self.yml
def get_jwt(username, password): if username in jwt_cache.keys(): return jwt_cache[username] # 在喂小保后台调接口时,请求头需要用到jwt参数,此参数从登录接口中获取 url = 'https://test.wxb.com.cn/dalaran/login' requests.packages.urllib3.disable_warnings() try: rs = requests.post(url=url, data={"userName": username, "pwd": password}, headers={"Content-Type": "application/x-www-form-urlencoded", "jwt": ""}, verify=False) if json.loads(rs.text)['code'] == 10000 and json.loads(rs.text)['msg'] == 'Success': jwt = json.loads(rs.text)['data']['jwt'] jwt_cache[username] = jwt logger.info(f"获取jwt:{jwt} 成功") return jwt else: logger.info(f"{rs.text} 获取jwt失败") except Exception as e: logger.error(f"调用获取jwt接口失败{e}")
def get_casename_step(self): """ 从yaml文件中读取用例描述,用例编号,用例执行步数 """ fp = None casesteps = [] try: fp = open(self.file_path, encoding='utf-8') data = yaml.safe_load(fp) except FileNotFoundError: logger.error(f"文件{self.file_path}不存在,请检查文件路径是否正确") for testcase in data.keys(): """ data.keys(),从data中把用例编号全部取出,结果例如['testcase1', 'testcase2'] """ try: if data[testcase]['Enabled'].upper() == "YES": """ Enabled:YES为用例有效,NO为用例无效 """ stepcount = json.dumps(data[testcase]).count("step") """ 先把data[testcase]转为字符串,然后统计每个case中step的数目,作为用例执行步数 """ case_step = { 'casename': data[testcase]['casename'], 'caseno': testcase, 'step': stepcount } """ case_step:包含了单个用例的用例描述,用例编号,用例执行步数 """ casesteps.append(case_step) """ casesteps:包含了一个yaml中所有用例的用例描述,用例编号,用例执行步数,把单个用例的结果加入到列表中 """ else: pass except Exception as e: logger.error("用例编号{}取用例描述,用例执行步数异常".format(testcase)) return casesteps
def start(self,filePath,defNameHead,skipDirs=None): try: for root,dirs,files in os.walk(filePath): if skipDirs: for i in range(len(skipDirs)): skipDirs[i] = filePath + u'/' + skipDirs[i].replace('\\','/').replace('//','/') root = root.replace('\\','/') if root in skipDirs: logger.info('跳过目录 %s'%(root)) continue if not files: logger.warning('文件列表为空') return {'result':1,'msg':'文件列表为空'} for i in files: result = self.makeCaseList(i,defNameHead) except Exception as e: logger.error('处理文件时异常 %s'%(e)) return {'result':1,'msg':'处理文件时异常 %s'%(e)} return {'result':0,'msg':'处理文件成功','testCaseCount':self.testCaseCount,'pyCaseFileCount':self.pyCaseFileCount}
def get_source(self, caseno=None, steps=None): """ 获得yaml文件中的单个用例数据 :param caseno:用例编号 :param steps:用例执行步数 """ try: d = self.yml[caseno] except KeyError: logger.error(f"当前数据:{self.yml} 中找不到{caseno}!!!") # d1=replace_params(d,paramsvalues) reqdatas = [] """ for中根据传入的执行步数,取每一步的数据作为一个字典,然后添加到reqdatas列表中 步数从1开始计算,所以在传入的步数基础上加1 """ for num in range(1, int(steps) + 1): step = 'step' + str(num) reqdatas.append(d[step]) return reqdatas
def get_function_args(content: Any) -> List[List]: """ 获取方法参数 :param content: :return: """ pattern = r'\$.*?\)' result = list() if not isinstance(content, str): content = str(content) match_list = re.findall(pattern, content) # 没有匹配上直接返回 if not match_list: return None for match in match_list: start_index = str(match).index("(") + 1 end_index = match.index(")") try: args = match[start_index:end_index] # 没有参数 if not args: # 写入空list result.append(list()) continue split = args.split(",") # result.append(list(map(lambda x: int(x.strip()), split))) args_list = [] for argument in split: try: args_list.append(int(argument)) except Exception as e: args_list.append(str(argument)) result.append(args_list) # todo 字典类型 except Exception as e: logger.error(e) return result
def check_result(self): logger.info('接口返回的结果【用来断言】为 {}'.format(self.response_data)) print('断言的集合为 {}'.format(self.validate)) print('接口返回的结果【用来断言】为 {}'.format(self.response_data)) logger.info('yml种预期的validate is {}'.format(self.validate)) if self.validate is not None: val_keys = get_keys(self.validate) logger.info('要断言的validate类型列表为 {}'.format(val_keys)) try: for i in val_keys: if i == 'expected_code': # if self.validate['expected_code'] is not None: self.check_code() # else: # print('此step下的validate节点下的 {} 类型节点的值为空,无需断言'.format('expected_code')) elif i == 'assert_kes_value': self.check_keys_value() elif i == 'assert_in_text': self.check_in_text() elif i == 'assert_key_exists': self.check_key() logger.info('此step中的validate "断言成功') except: logger.error('此step中的validate "断言失败" ') assert False, '此step中的validate "断言失败" ' # except Exception as e: # # logger.error(e) # assert False, logger.error('此step中的validate "断言失败" ') else: logger.warning('此step中的validate为 {}所以没有要断言的内容'.format( self.validate)) assert True, '没有要断言的内容'
def read_yaml_val(testcase_no, step_no, path): """ :param testcase_no: testcase1。。。 :param step_no: step1 中的1 传入的是第几步的 具体数值 不是总步数 :param path: :return: """ steps = HandleYaml(path).get_casename_step() logger.info( '{} 中的所有steps is \n {}' .format(path, steps)) val_ = None # '测试数据yml {} 中没有目标用例 {} 或 目标用例 {} 中没有目标step {}'.format(path, testcase_no, testcase_no, step_no) ll = '' for i in steps: ll = ll + (''.join(get_target_value('caseno', i, []))) if testcase_no not in ll: logger.error('用例集中没有 {} 这个用例'.format(testcase_no)) else: for i in steps: if testcase_no in i.values(): all_step = i['step'] if step_no in [i for i in range(1, all_step + 1)]: # print('all step {}'.format(all_step)) res_ = HandleYaml(path).get_source(testcase_no, all_step) step_no = step_no - 1 val_ = res_[step_no] else: logger.error('{} 中没有步骤 {}'.format(testcase_no, step_no)) return val_['validate']
def get_casename_step(self): """ 从yaml文件中读取用例描述,用例编号,用例执行步数 """ casesteps = [] for testcase in self.yml.keys(): """ data.keys(),从data中把用例编号全部取出,结果例如['testcase1', 'testcase2'] """ try: if self.yml[testcase]['Enabled'].upper() == "YES": """ Enabled:YES为用例有效,NO为用例无效 """ stepcount = json.dumps(self.yml[testcase]).count("step") """ 先把data[testcase]转为字符串,然后统计每个case中step的数目,作为用例执行步数 """ case_step = { 'casename': self.yml[testcase]['casename'], 'caseno': testcase, 'step': stepcount } """ case_step:包含了单个用例的用例描述,用例编号,用例执行步数 """ casesteps.append(case_step) """ casesteps:包含了一个yaml中所有用例的用例描述,用例编号,用例执行步数,把单个用例的结果加入到列表中 """ else: pass except Exception as e: logger.error("用例执行步数异常{}".format(e)) return casesteps
def run_request(self): """ :param h3:从前面接口返回报文中取出后面接口header中参数化的实际值 :param d3:从前面接口返回报文中取出后面接口data中参数化的实际值 """ self.get_datasource() self.respo = [] # self.h3 = {} # self.d3 = {} for data in self.source: # host = data['general']['host'] # host = self.pre_host(host) host = get_app_host() url = data['general']['path'] if 'wxb' not in url: url = host + data['general']['path'] method = data['general']['method'] header = data["headers"] pay_load = data['data'] if header and (method.lower() == "post") and ( header['Content-Type'] != 'application/json'): if 'setparam' in data: if data['setparam'] is not None: nn = GetParamBySequenceCall().get_params( data['setname'], data['setparam']) global_vars.update(nn) else: pass header, request_data = self.pre_request(header, pay_load) try: logger.info( "********************开始执行请求********************") logger.info('请求头部为 :{}'.format(header)) logger.info('请求方法为 :{}'.format(method)) logger.info('请求路径为 :{}'.format(url)) logger.info('请求数据为 :{}'.format(request_data)) requests.packages.urllib3.disable_warnings() rs = requests.post(url=url, data=request_data, headers=header, verify=False) logger.info(f"接口请求成功,响应为:{rs.text}") except Exception as e: logger.error( f"接口请求失败,接口请求url:{url}\n接口请求参数:{request_data}\n接口请求头:{header}\n" f"接口响应状态码:{rs.status_code}\n错误信息:{e}") resp = json.loads(rs.text) http_code = rs.status_code if data['extract'] is not None: """ self.h3.update()根据待提取的字段,提取响应报文中待提取字段实际值,并添加到h3字典中 self.d3.update()根据待提取的字段,提取响应报文中待提取字段实际值,并添加到d3字典中 """ eval_jsonpath_str(json.loads(rs.text), data['extract']) self.respo.append(resp) self.respo.append(http_code) elif header and (method.lower() == "post") and (header['Content-Type'] == 'application/json'): if 'setparam' in data: if data['setparam'] is not None: nn = GetParamBySequenceCall().get_params( data['setname'], data['setparam']) global_vars.update(nn) else: pass header, request_data = self.pre_request(header, pay_load) try: logger.info( "********************开始执行请求********************") logger.info('请求头部为 :{}'.format(header)) logger.info('请求方法为 :{}'.format(method)) logger.info('请求路径为 :{}'.format(url)) logger.info('请求数据为 :{}'.format(request_data)) requests.packages.urllib3.disable_warnings() rs = requests.post(url=url, data=json.dumps(request_data), headers=header, verify=False) logger.info(f"接口请求成功,响应为:{rs.text}") except Exception as e: logger.error( f"接口请求失败,接口请求url:{url}\n接口请求参数:{request_data}\n接口请求头:{header}\n" f"接口响应状态码:{rs.status_code}\n错误信息:{e}") resp = json.loads(rs.text) http_code = rs.status_code if data['extract'] is not None: eval_jsonpath_str(json.loads(rs.text), data['extract']) self.respo.append(resp) self.respo.append(http_code) elif not header and (method.lower() == "post"): if 'setparam' in data: if data['setparam'] is not None: nn = GetParamBySequenceCall().get_params( data['setname'], data['setparam']) global_vars.update(nn) else: pass header, request_data = self.pre_request(header, pay_load) try: logger.info( "********************开始执行请求********************") logger.info('请求头部为 :{}'.format(header)) logger.info('请求方法为 :{}'.format(method)) logger.info('请求路径为 :{}'.format(url)) logger.info('请求数据为 :{}'.format(request_data)) requests.packages.urllib3.disable_warnings() rs = requests.post(url=url, data=request_data, headers={"ev": "v4"}, verify=False) logger.info(f"接口请求成功,响应为:{rs.text}") except Exception as e: logger.error( f"接口请求失败,接口请求url:{url}\n接口请求参数:{request_data}\n接口请求头:{header}\n" f"接口响应状态码:{rs.status_code}\n错误信息:{e}") resp = json.loads(rs.text) http_code = rs.status_code if data['extract'] is not None: eval_jsonpath_str(json.loads(rs.text), data['extract']) self.respo.append(resp) self.respo.append(http_code) elif header and (method.lower() == "get"): if 'setparam' in data: if data['setparam'] is not None: nn = GetParamBySequenceCall().get_params( data['setname'], data['setparam']) global_vars.update(nn) else: pass header, request_data = self.pre_request(header, pay_load) try: logger.info( "********************开始执行请求********************") logger.info('请求头部为 :{}'.format(header)) logger.info('请求方法为 :{}'.format(method)) logger.info('请求路径为 :{}'.format(url)) logger.info('请求数据为 :{}'.format(request_data)) requests.packages.urllib3.disable_warnings() rs = requests.get(url=url, params=request_data, headers=header, verify=False) logger.info(f"接口请求成功,响应为:{rs.text}") except Exception as e: logger.error( f"接口请求失败,接口请求url:{url}\n接口请求参数:{request_data}\n接口请求头:{header}\n" f"接口响应状态码:{rs.status_code}\n错误信息:{e}") resp = json.loads(rs.text) http_code = rs.status_code if data['extract'] is not None: eval_jsonpath_str(json.loads(rs.text), data['extract']) self.respo.append(resp) self.respo.append(http_code) # elif header and (method.lower() == "get") and (header['Content-Type'] == 'application/json'): # header, request_data = self.pre_request(header, pay_load) # try: # logger.info( # f"********************开始执行请求********************\t url:{url} \t pay_load:{request_data}") # requests.packages.urllib3.disable_warnings() # rs = requests.get(url=url, params=json.dumps(request_data), headers=header, verify=False) # logger.info(f"接口请求成功,响应为:{rs.text}") # except Exception as e: # logger.error(f"接口请求失败,接口请求url:{url}\n接口请求参数:{request_data}\n接口请求头:{header}\n" # f"接口响应状态码:{rs.status_code}\n错误信息:{e}") # resp = json.loads(rs.text) # http_code = rs.status_code # if data['extract'] is not None: # eval_jsonpath_str(json.loads(rs.text), data['extract']) # self.respo.append(resp) # self.respo.append(http_code) elif not header and (method.lower() == "get"): if 'setparam' in data: if data['setparam'] is not None: nn = GetParamBySequenceCall().get_params( data['setname'], data['setparam']) global_vars.update(nn) else: pass header, request_data = self.pre_request(header, pay_load) try: logger.info( "********************开始执行请求********************") logger.info('请求头部为 :{}'.format(header)) logger.info('请求方法为 :{}'.format(method)) logger.info('请求路径为 :{}'.format(url)) logger.info('请求数据为 :{}'.format(request_data)) requests.packages.urllib3.disable_warnings() rs = requests.get(url=url, params=request_data, headers={"ev": "v4"}, verify=False) logger.info(f"接口请求成功,响应为:{rs.text}") except Exception as e: logger.error( f"接口请求失败,接口请求url:{url}\n接口请求参数:{request_data}\n接口请求头:{header}\n" f"接口响应状态码:{rs.status_code}\n错误信息:{e}") resp = json.loads(rs.text) http_code = rs.status_code if data['extract'] is not None: eval_jsonpath_str(json.loads(rs.text), data['extract']) self.respo.append(resp) self.respo.append(http_code) # else: # self.respo = {"code": False, "data": False} # logger.info("没有找到对应的请求方法!") # logger.info("请求接口结果:\n {}".format(self.respo)) return self.respo