def input_address(self, address=None): # 判断详细地址输入框是否为空,为空时输入信息 if self.find_element(loc.address_loc).get_attribute("value"): pass else: logger.info("--- 输入详细地址:{} ---".format(address)) self.find_element(loc.address_loc).send_keys(address)
def select_linker(self, tel): logger.info("--- 点击采购经理人手机号输入框 ---") self.find_element(loc.linker_loc).click() # 获取所有采购经理人的手机号 tels = self.find_elements(loc.linker_tel_loc) # 判断要选择的采购经理人是否在列表中 try: for i in tels: if i.text == tel: i.click() logger.info("--- 选择采购经理人 : {} ---".format(tel)) break logger.info("--- 选择采购经理人后点击确定 ---") self.find_element(loc.linker_yes_loc).click() try: # 判断有没有错误提示信息 self.wait_ele_visible(loc.linker_err_msg_loc, visible=None) except: logger.exception("--- 提示信息:请选择采购经理人 ---") raise else: logger.info("--- 选择采购经理人成功 ---") except: logger.info("--- 错误信息:选择的采购经理人不存在 ---")
def relace_case_with_re_v2(case_dict): # 实例化HandleYaml类,读取data.yaml中的数据 global_data = HandleYaml("data.yaml").data case_str = str(case_dict) # 正则提取 data_mark_list = re.findall("#(\w+)#", case_str) # 列表 logger.info("从测试用例中,正则提取之后的结果:{}".format(data_mark_list)) # 若有phone字段,则先生成一个未注册的手机号码,并设置为Data类的phone属性 if "phone" in data_mark_list: logger.info("有phone字段,需要生成一个新的尚未注册的手机号,并设置到Data类的phone属性") get_new_phone() if data_mark_list: # 列表不为空 for mark in data_mark_list: # 遍历列表里的值 # mark可能在数据配置文件data.yaml当中,也有可能在Data当中。 if mark in global_data.keys(): case_str = case_str.replace(f"#{mark}#", str(global_data[mark])) logger.info( f"从data.yaml中取数据,替换mark: #{mark}#,替换后mark值为:{global_data[mark]}" ) else: # 从Data类当中,用对应的数据,去替换。 case_str = case_str.replace(f"#{mark}#", getattr(Data, mark)) logger.info( f"从Data类中取数据,替换mark: #{mark}#,替换后mark值为:{getattr(Data, mark)}" ) logger.info(f"替换完成之后的用例数据(字符串类型)为:\n {case_str}") return eval(case_str)
def test_setup(self, case): logger.info("=====开始执行前置操作=====") logger.info("从excel当中,读取的测试用例为:{}".format(case)) # 替换 case = relace_case_with_re_v2(case) # 发起http请求 resp = self.hr.send_request(case["method"], case["url"], case["request_data"])
def find_elements(self, loc): # 先等待元素可见 self.wait_ele_visible(loc) logger.info("查找元素:{}".format(loc)) try: self.driver.find_element(*loc) return self.driver.find_elements(*loc) except: logger.exception("元素查找失败,找不到该元素,开始截取当前页面图像".format(loc)) self.save_screenshot() raise
def is_user_exist(self): # 判断账套信息是否存在 logger.info("--- 等待账套信息可见 ---") try: self.wait_ele_visible(loc.user_info_loc) except: logger.exception("--- 账套信息不可见 ---") return False else: logger.info("--- 账套信息可见 ---") return True
def select_kind(self, kind): logger.info("--- 选择采购类别:{} ---".format(kind)) # 获取所有采购类别的名字 kinds = self.find_elements(loc.kind_loc) try: # 判断想选择的采购类别是否在列表中,存在时点击选择 for i in kinds: if i.text == kind: i.click() break except: logger.exception("--- 错误信息:选择的采购类别不存在 ---")
def result(self, value): logger.info("--- 判断是否查询到结果 ---") # 定位到所有的查询结果 all_result = self.find_elements(loc.result_loc) try: # 判断查询条件是否显示在查询结果中 for i in all_result: if value == i.text: logger.info("--- 查询到结果 ---") return True except: logger.exception("--- 未查到结果 ---") return False
def wait_ele_visible(self, loc, visible=True): if visible: # visible为true时,执行元素是否可见的判断 logger.info("等待元素:{} 是否可见".format(loc)) try: wait = WebDriverWait(self.driver, 20, 0.5) wait.until(EC.visibility_of_element_located(loc)) sleep(1) except: logger.exception("等待元素:{} 可见失败,元素当前不可见".format(loc)) raise else: logger.info("等待元素:{} 可见成功,元素当前可见") else: # visible为false时,执行元素是否不可见的判断 logger.info("等待元素:{} 是否不可见".format(loc)) try: wait = WebDriverWait(self.driver, 20, 0.5) wait.until(EC.invisibility_of_element_located(loc)) sleep(1) except: logger.exception("等待元素:{} 不可见失败,元素当前可见".format(loc)) raise else: logger.info("等待元素:{} 不可见成功,元素当前不可见")
def get_json_compare_res(self, expeced_exprs_str, resp_dict): # 转成字典 expeced_exprs_dict = eval(expeced_exprs_str) # 遍历字典,通过jsonpath,从resp_dcit当中提取对应的数据,更新字典值 for key, value in expeced_exprs_dict.items(): logger.info("提取表达式为:{},期望结果值为:{}".format(key, value)) # 将jsonpath表达式的key,通过jsonpath提取后,得到对应的值 actual_value_list = jsonpath(resp_dict, key) print(type(actual_value_list)) # 将提取的表达式与期望的值做等值比较,没有提取到的值为false,提取到的是True if isinstance(actual_value_list, list): if actual_value_list[0] == value: self.json_compare_res[ f"jsonpath-{key}-actual-{value}-expected-{actual_value_list[0]}"] = True else: self.json_compare_res[ f"jsonpath-{key}-actual-{value}-expected-{actual_value_list[0]}"] = False logger.info("提取的值与期望值的比对结果为:{}".format(self.json_compare_res[ "jsonpath-{}-actual-{}-expected-{}".format( key, value, actual_value_list[0])])) # jsonpath如果提取到对应的值是False else: logger.error( "在响应结果当中,根据jsonpath表达式:{} 没有提取到值。提取结果为False".format(key)) self.json_compare_res[ "jsonpath_{}_actual_{}_expected_{}".format( key, value, actual_value_list)] = False logger.info("所有实际结果与预期结果的比对情况:") for key, value in self.json_compare_res.items(): logger.info("{}:{}".format(key, value)) print("--------------------------------------------")
def select_linker(self, linker_name): logger.info("--- 选择采购经理人:{} ---".format(linker_name)) # 点击选择按钮 self.find_element(loc.linker_loc).click() # 获取所有采购经理人的名字 names = self.find_elements(loc.linker_name_loc) try: # 判断想选择的采购经理人是否在列表中,存在时点击选择 for i in names: if i.text == linker_name: i.click() break logger.info("--- 选择采购经理人后,点击确定 ---") self.find_element(loc.select_linker_yes_loc).click() try: # 判断是否有错误信息提示框 self.wait_ele_visible(loc.linker_msg_loc, visible=None) except: logger.exception("--- 提示信息:请选择采购经理人 ---") raise else: logger.info("--- 选择采购经理人成功 ---") except: logger.info("--- 错误信息:选择的采购经理人不存在 ---")
def test_02_select_order_by_order_id(self): logger.info("--- 输入订单编号查询 ---") # 点击供货管理--订单管理 self.hp.click_order() # 输入订单id self.op.input_order_id(rd["order_id"]) # 点击查询 self.op.click_select() # 断言 try: self.assertTrue(self.op.result(rd["order_id"])) logger.info("--- 断言成功 ---") except: logger.exception("--- 断言失败 ---")
def __init__(self, driver): self.driver = driver lp = LoginPage(self.driver) # 登录页 hp = HomePage(self.driver) # 首页 # 打开网址 lp.open_url(rd["url"]) # 登录页 lp.login_other_method(rd["user"], rd["password"]) # 判断登录是否成功 try: if hp.is_user_exist(): logger.info("--- 登录成功,进入首页 ---") except: logger.exception("--- 登录失败 ---")
def test_play(self, case): logger.info("用例开始执行,用例{}:{}".format(case["id"], case["title"])) # 数据替换,替换Excel中request_data中contId 正则表达式 (?<=contId=).*?(?=&) # case = replace_mark_with_data(cases,"#contId#","661543514") # 发起请求 response = send_request( method=case["method"], url=case["api_url"], data=case["request_data"]) # 将Excel的json转为dict expected = json.loads(case["expected"]) logger.info("期望结果为{}".format(expected)) # 读取Excel中的jsonpath check_jsonpath_contid = case["check_jsonpath_contId"] check_jsonpath_contname = case["check_jsonpath_contName"] logger.info( "本次jsonpath请求contId为:{},contName为{}".format( check_jsonpath_contid, check_jsonpath_contname)) # 对code contId contName 进行断言 assert response.json()["code"] == expected["code"] assert jsonpath.jsonpath( response.json(), check_jsonpath_contid) == jsonpath.jsonpath( expected, check_jsonpath_contid) assert jsonpath.jsonpath( response.json(), check_jsonpath_contname) == jsonpath.jsonpath( expected, check_jsonpath_contname) allure.attach(f'{response.json ()["code"]}=={expected["code"]}', "第一次断言", allure.attachment_type.TEXT) allure.attach( f'{response.json ()["code"]} == {expected["code"]}', "第二次断言", allure.attachment_type.TEXT) allure.attach( f'{jsonpath.jsonpath (response.json (),check_jsonpath_contname )} == {jsonpath.jsonpath ( expected,check_jsonpath_contname )}', "第二次断言", allure.attachment_type.TEXT)
def send_request(self, method, url, data=None, token=None): logger.info("===== 发送一次http请求 =====") logger.info("请求的mehtod为:{}".format(method)) logger.info("请求的url为:{}".format(url)) # 请求url地址处理 url = self.__deal_url(url) # 处理请提头部信息 self.__deal_data(data) # 处理请求数据 self.__deal_token(token) # 发送一次http请求,传入method,url,data,token信息 if method.upper() == "GET": response = requests.get(url, params=self.data, headers=self.headers) elif method.upper() == "POST": response = requests.post(url, json=self.data, headers=self.headers) else: response = requests.patch(url, json=self.data, headers=self.headers) logger.info("响应的code为:{}".format(response.status_code)) logger.info("响应的msg为:{}".format(response.json())) return response
def test_login_success(self): """成功登录流程""" # 手动输入验证码方式 self.lp.login_other_method(rd["user"], rd["password"]) # 识别图片验证码方式 # LoginPage(self.driver).login(rd["user"], rd["password"]) # 断言 try: self.assertTrue(self.hp.is_user_exist()) except: logger.exception("--- 断言:登录失败 ---") else: logger.info("--- 断言:登录成功 ---") # 点击账套信息 self.hp.click_user_info() # 点击退出按钮 self.hp.click_exit()
def test_register(self, case): logger.info("===== 开始执行第一个测试用例 =====") logger.info("从excel中读取的测试数据为:{}".format(case)) logger.info("从excel中读取的测试数据为:{}".format(type(case))) # 替换数据 case = relace_case_with_re_v2(case) # 发起一次http请求 resp = self.hr.send_request(case["method"], case["url"], case["request_data"]) resp = resp.json() if case["expected"]: self.hassert.get_json_compare_res(case["expected"], resp) sleep(0.2) if case["check_sql"]: self.hassert.init_sql_conn() self.hassert.get_multi_sql_compare_resp(case["check_sql"]) self.hassert.close_sql_conn()
def select_manu(self, manu_name): logger.info("--- 选择生产企业:{} ---".format(manu_name)) # 点击生产企业选择框 self.find_element(loc.manu_loc).click() # 获取所有生产企业的名字 names = self.find_elements(loc.manu_name_loc) try: # 判断想选择的生产企业是否在列表中,存在时点击选择 for i in names: if i.text == manu_name: i.click() break logger.info("--- 选择生产企业后,点击确定 ---") # 选择生产企业后点击确定 self.find_element(loc.manu_yes_loc).click() try: # 判断是否有错误信息提示框 self.wait_ele_visible(loc.manu_msg_loc, visible=None) except: logger.exception("--- 提示信息:请选择生产企业 ---") raise else: logger.info("--- 选择生产企业成功 ---") except: logger.exception("--- 错误信息:选择的生产企业不存在 ---")
def assert_result(self): sql_com_res_flag = True json_com_res_flag = True # json响应结果比对中,如果没有False,则全部比对通过,否则,表示比对失败 if self.json_compare_res and False in self.json_compare_res.values(): logger.info("sql断言失败,用例失败!请检查sql比对结果为False的!") sql_com_res_flag = False # 判断sql_com_res_flag不为空,说明有sql比对 if self.sql_comp_res: # self.sql_com_res_flag为列表,说明有多条sql语句进行比对结果,则需要一个个确认是否有False if isinstance(self.sql_comp_res, list): for res in self.sql_comp_res: if False in res.values(): sql_com_res_flag = False # self.sql_com_res_flag为字典,则说明有一条sql语句比对结果,只需要确认是否为False if isinstance(self.sql_comp_res, dict): if False in self.sql_comp_res.values(): sql_com_res_flag = False if sql_com_res_flag is False or json_com_res_flag is False: logger.info("sql语句断言失败或者json响应数据段断言失败!") logger.error(f"sql语句断言结果为:{sql_com_res_flag}") logger.error(f"json响应结果断言结果为:{json_com_res_flag}") else: logger.info("用例执行通过!")
def select_product(self): # 选择料型-板料-冲子料 logger.info("--- 选择料型 ---") self.find_element(loc.product_loc).click() logger.info("--- 选择板料 ---") self.find_element(loc.product_name_loc).click() logger.info("--- 选择一级 ---") self.find_element(loc.product_name1_loc).click()
def send_request(method, url, data=None, token=None): headers = __hand_header(token) url = __get_url(url) data = __get_json_data(data) # 配合proxies,开启fiddler抓包 if method.upper() == 'GET': # verify 是否验证服务器的SSL证书 # proxies 开启代理调试 response = requests.get(url, params=data, headers=headers, verify=False, proxies=None) elif method.upper() == 'POST': response = requests.post(url, json=data, headers=headers, verify=False, proxies=None) logger.info('响应状态码为:{}'.format(response.status_code)) # 不是json数据则报错,待优化 logger.info('响应内容为:{}'.format(response.json())) debug = {'http': 'http://localhost:8888', 'https': 'http://localhost:8888'} # allure allure.attach(str(url), "请求地址", allure.attachment_type.TEXT) allure.attach(f"{headers}", "请求头", allure.attachment_type.TEXT) allure.attach(f"{method}", "请求方法", allure.attachment_type.TEXT) allure.attach(str(data), "请求参数", allure.attachment_type.TEXT) allure.attach(str(response.status_code), "反回状态码", allure.attachment_type.TEXT) allure.attach(response.text, "响应结果", allure.attachment_type.TEXT) return response
def loopGetCode(self): """ 循环判断获取正确的图片code :return: 返回识别出的验证码 """ self.getCodeImg() code = self.remove(self.getCode()) # 循环前获取code字数 codeNumBf = len(code) # 如果获取图片的code值为空或者不满足4位数进行循环 while (code == "") or (codeNumBf != 4): # 重新获取验证码 self.img_el.click() sleep(1) self.getCodeImg() # 获取验证码图片 code = self.remove(self.getCode()) # 循环后获取code字数 codeNumAf = len(code) if code == "": # print("code获取为空值=================") logger.info("验证码获取为空值") continue elif codeNumAf != 4: # print("code获取不是4位数字=============") logger.info("验证码获取不是4位数字") continue else: # print("识别code成功!") logger.info("验证码识别成功") # 识别成功退出循环 break # print("=============输出的验证码为:" + code) logger.info("输出的验证码为:{}".format(code)) # 输出满足条件的code return code
def input_begin_time(self, begin_time): logger.info("--- 输入采购开始时间 : {} ---".format(begin_time)) self.find_element(loc.begin_time_loc).clear() self.find_element(loc.begin_time_loc).send_keys(begin_time)
def input_settle_cycle(self, settle_cycle): logger.info("--- 输入结算周期:{} ---".format(settle_cycle)) self.find_element(loc.settle_cycle_loc).send_keys(settle_cycle)
def input_purchase_amount(self, purchase_amount): logger.info("--- 输入采购数量:{} ---".format(purchase_amount)) self.find_element(loc.purchase_amount_loc).send_keys(purchase_amount)
def input_purchase_unit_price(self, purchase_unit_price): logger.info("--- 输入采购单价:{} ---".format(purchase_unit_price)) self.find_element( loc.purchase_unit_price_loc).send_keys(purchase_unit_price)
def input_sale_unit_price(self, sale_unit_price): logger.info("--- 输入销售单价:{} ---".format(sale_unit_price)) self.find_element(loc.sale_unit_price_loc).send_keys(sale_unit_price)
def submit_click(self): logger.info("--- 点击提交订单 ---") self.find_element(loc.submit_loc).click() logger.info("--- 提交订单成功 ---")
def input_desc(self, desc): logger.info("--- 输入说明:{} ---".format(desc)) self.find_element(loc.desc_loc).send_keys(desc)
def input_size(self, size): logger.info("--- 输入规格:{} ---".format(size)) self.find_element(loc.size_loc).send_keys(size)