当前位置:首页 > Web开发 > 正文

web自动化针对PO模式进行二次封装之 basepage

2024-03-31 Web开发

  在 PO 模式傍边, 我们做到了 页面东西 与 测试用例 的 疏散,但在页面东西编写时,我们仍然还有优化的空间。页面东西有一些配合的根基操纵 ,可以封装起来,并可以在根基操纵傍边加上 日志 和 异常截图 的措置惩罚惩罚。好比说我们在查找元素时,都需要期待,在PO模式傍边, 需要都写上 期待和查找元素,那么就可以将其封装起来,包孕其它的一些好比:文本获取、元素属性获取、鼠标操纵、窗口切换、iframe切换、 alert弹框封锁、 文件上传、下拉框选择.....

  当脚本运行的过程中,呈现了用例掉败,我们但愿可以通过 日志和截图 来分析掉败的原因,selenium 并没有主动生成日志和截图,所以需要在代码中加上,使用 webdriver 的 save_ screenshot 要领来截图,日志和截图会记录自动化用例的执行过程,并且,在用例的任何一个法式呈现了异常城市记录异常信息并生成相应的截图。固然为了更美不雅观地跟allure集成,自然也需要将以异常截图展示在 allure 呈报中,以下就是 basepage.py 的部分内容:

# 因为在每一个测试用例傍边,无论测试用例的那一步掉败了,我们都要能够实时捕获异常/整个用例执行完毕,输出操纵日志/生成掉败截图 # 好比接口测试用例用 try --except 来判断异常, # web测试用例中由什么来组成,页面东西 + 测试数据 + 断言 = selenium 中webdriver 网页根基操纵,这样就可以从底层进行捕获, # 1、封装根基关键字,任何一个页面操纵都可以实时捕获异常/输出操纵日志/掉败截图 import time from datetime import datetime import allure # 呈报 from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.select import Select from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.remote.webdriver import WebDriver from Common.handle_logger import case_logger # 日志封装 from Common.constants import OUTPUTS_SCREENSHOTS_DIR # 页面截图生存的路径 from Common.upload_file import upload # 上传文件封装 class BasePage: ‘‘‘ BasePage类,针对PageObjects类的二次封装 ‘‘‘ def __init__(self, driver: WebDriver): self.driver = driver def wait_element_to_be_visible(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 期待元素可见 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("开始期待页面元素<{}>是否可见!".format(loc)) start_time = time.time() # 没有抛出异常的时间 WebDriverWait(self.driver, timeout, frequency).until(EC.visibility_of_element_located(loc)) except Exception as e: case_logger.error("页面元素<{}>期待可见掉败!".format(loc)) # 异平日志捕获 self.save_screenshot(img_doc) # 异常截图--通过截图名称,知道是哪个页面或者哪个模块堕落了。 raise e else: end_time = time.time() # 抛出异常的时间 case_logger.info("页面元素<{}>期待可见,期待时间:{}秒".format(loc, round(end_time - start_time, 2))) def wait_element_to_be_click(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 期待元素可点击 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("开始期待页面元素<{}>是否可点击!".format(loc)) start_time = time.time() WebDriverWait(self.driver, timeout, frequency).until(EC.element_to_be_clickable(loc)) except Exception as e: case_logger.error("页面元素<{}>期待可点击掉败!".format(loc)) self.save_screenshot(img_doc) raise e else: end_time = time.time() case_logger.info("页面元素<{}>期待可点击,期待时间:{}秒".format(loc, round(end_time - start_time, 2))) def wait_element_to_be_exist(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 期待元素存在 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("开始期待页面元素<{}>是否存在!".format(loc)) start_time = time.time() WebDriverWait(self.driver, timeout, frequency).until(EC.presence_of_element_located(loc)) except Exception as e: case_logger.error("页面元素<{}>期待存在掉败!".format(loc)) self.save_screenshot(img_doc) raise e else: end_time = time.time() case_logger.info("页面元素<{}>期待存在,期待时间:{}秒".format(loc, round(end_time - start_time, 2))) def save_screenshot(self, img_doc): ‘‘‘ 页面截屏生存截图 :param img_doc: 截图说明 :return: ‘‘‘ file_name = OUTPUTS_SCREENSHOTS_DIR + "/{}_{}.png".format( datetime.strftime(datetime.now(), "%Y-%m-%d %H-%M-%S"), img_doc) # 生存到阿谁路径,生存的名称为 self.driver.save_screenshot(file_name) # 存储到指定目录下 with open(file_name, mode=rb) as f: file = f.read() allure.attach(file, img_doc, allure.attachment_type.PNG) case_logger.info("页面截图文件生存在:{}".format(file_name)) def get_element(self, loc, img_doc): ‘‘‘ 获取页面中的元素 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :return: WebElement东西 ‘‘‘ case_logger.info("在{}中查找元素<{}>".format(img_doc, loc)) try: ele = self.driver.find_element(*loc) except Exception as e: case_logger.error("在{}中查找元素<{}>掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e else: return ele def get_elements(self, loc, img_doc): ‘‘‘ 获取页面中的所有元素 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :return: WebElement东西 ‘‘‘ case_logger.info("在{}中查找所有元素<{}>".format(img_doc, loc)) try: ele = self.driver.find_elements(*loc) except Exception as e: case_logger.error("在{}中查找所有元素<{}>掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e else: return ele def input_text(self, loc, text, img_doc, timeout=20, frequency=0.5): ‘‘‘ 对输入框输入文本内容 :param text: 输入的文本内容 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}中输入元素<{}>的内容为{}".format(img_doc, loc, text)) self.wait_element_to_be_visible(loc, img_doc, timeout, frequency) self.get_element(loc, img_doc).send_keys(text) except Exception as e: case_logger.error("在元素<{}>中输入内容{}掉败!".format(loc, text)) self.save_screenshot(img_doc) raise e def clear_text(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 断根文本框的内容 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}中断根元素<{}>的文本内容".format(img_doc, loc)) self.wait_element_to_be_click(loc, img_doc, timeout, frequency) self.get_element(loc, img_doc).clear() except Exception as e: case_logger.error("在{}中断根元素<{}>的文本内容掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e def click_button(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 点击按钮 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}中点击元素<{}>".format(img_doc, loc)) self.wait_element_to_be_click(loc, img_doc, timeout, frequency) self.get_element(loc, img_doc).click() except Exception as e: case_logger.error("在{}中点击元素<{}>掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e def get_element_text(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 获取WebElement东西的文本值 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: WebElement东西的文本值 ‘‘‘ try: case_logger.info("在{}中获取元素<{}>的文本值".format(img_doc, loc)) self.wait_element_to_be_visible(loc, img_doc, timeout, frequency) # 期待元素可见 text = self.get_element(loc, img_doc).text # 找元素 except Exception as e: case_logger.error("在{}中获取元素<{}>的文本值掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e else: case_logger.info("获取到的元素文本值为:{}".format(text)) return text def get_elements_text(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 获取WebElement东西的所有文本值 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: WebElement东西的文本值的列表 ‘‘‘ try: case_logger.info("在{}中获取元素<{}>的所有文本值".format(img_doc, loc)) self.wait_element_to_be_visible(loc, img_doc, timeout, frequency) all_text = self.get_elements(loc, img_doc) text_list = [] for one_text in all_text: text_list.append(one_text.text) except Exception as e: case_logger.error("在{}中获取元素<{}>的所有文本值掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e else: case_logger.info("获取到的元素文本值列表为:{}".format(text_list)) return text_list def get_element_attr(self, attr_name, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 获取WebElement东西的属性值 :param attr_name: 属性名称 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: WebElement东西的属性值 ‘‘‘ try: case_logger.info("在{}中获取元素<{}>的属性{}的值".format(img_doc, loc, attr_name)) self.wait_element_to_be_exist(loc, img_doc, timeout, frequency) value = self.get_element(loc, img_doc).get_attribute(attr_name) except Exception as e: case_logger.error("在{}中获取元素<{}>的属性{}的值掉败!".format(img_doc, loc, attr_name)) self.save_screenshot(img_doc) raise e else: case_logger.info("获取到的元素属性{}的值为{}".format(attr_name, value)) return value def switch_to_frame(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 切换iframe页面 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}中按照元素<{}>进行iframe切换".format(img_doc, loc)) start_time = time.time() WebDriverWait(self.driver, timeout, frequency).until(EC.frame_to_be_available_and_switch_to_it(loc)) except Exception as e: case_logger.error("在{}中按照元素<{}>进行iframe切换掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e else: end_time = time.time() case_logger.info("在{}中按照元素<{}>进行iframe切换,期待时间:{}秒". format(img_doc, loc, round(end_time - start_time, 2))) def switch_to_default_content(self, img_doc): ‘‘‘ 切换iframe到main页面 :param img_doc: 截图说明 :return: ‘‘‘ try: case_logger.info("切换iframe到main页面") self.driver.switch_to.default_content() except Exception as e: case_logger.error("切换iframe到main页面掉败!") self.save_screenshot(img_doc) raise e def switch_to_parent(self, img_doc): ‘‘‘ 切换iframe到上一层页面 :param img_doc: 截图说明 :return: ‘‘‘ try: case_logger.info("切换iframe到上一层页面") self.driver.switch_to.parent_frame() except Exception as e: case_logger.error("切换iframe到上一层页面掉败!") self.save_screenshot(img_doc) raise e def upload_file(self, filename, img_doc, browser_type="chrome"): ‘‘‘ 非input标签的文件上传 :param filename: 文件名(绝对路径) :param img_doc: 截图说明 :param browser_type: 浏览器类型 :return: ‘‘‘ try: case_logger.info("上传文件({})".format(filename)) time.sleep(2) upload(filePath=filename, browser_type=browser_type) except Exception as e: case_logger.error("上传文件({})掉败!".format(filename)) self.save_screenshot(img_doc) raise e else: time.sleep(2) def suspend_mouse(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 鼠标悬浮 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}上按照元素<{}>进行悬浮".format(img_doc, loc)) self.wait_element_to_be_click(loc, img_doc, timeout, frequency) ele = self.get_element(loc, img_doc) ActionChains(self.driver).move_to_element(ele).perform() except Exception as e: case_logger.error("在{}上按照元素<{}>进行悬浮掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e def alert_close(self, img_doc, alert_type=alert, text=None, timeout=20, frequency=0.5): ‘‘‘ 弹框封锁 :param img_doc: 截图说明 :param alert_type: 弹框类型:alert/confirm/prompt :param text: prompt弹框输入的文本 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}中切换并封锁{}类型的弹框".format(img_doc, alert_type)) start_time = time.time() WebDriverWait(self.driver, timeout, frequency).until(EC.alert_is_present()) if alert_type in [alert, confirm]: self.driver.switch_to.alert.accept() elif alert_type == prompt: self.driver.switch_to.alert.send_keys(text) self.driver.switch_to.alert.accept() else: case_logger.error("不撑持{},请确认alert的类型".format(alert_type)) except Exception as e: case_logger.error("在{}中切换并封锁{}类型的弹框掉败!".format(img_doc, alert_type)) self.save_screenshot(img_doc) raise e else: end_time = time.time() case_logger.info("在{}中切换并封锁{}类型的弹框,,期待时间:{}秒". format(img_doc, alert_type, round(end_time - start_time, 2))) def select_action(self, loc, img_doc, content, select_type, timeout=20, frequency=0.5): ‘‘‘ Select操纵 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param content: select_by_要领的入参 :param select_type: select类型 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}上按照元素<{}>以{}方法进行下拉选择".format(img_doc, loc, select_type)) self.wait_element_to_be_click(loc, img_doc, timeout, frequency) ele = self.get_element(loc, img_doc) if select_type == index: Select(ele).select_by_index(content) elif select_type == value: Select(ele).select_by_value(content) elif select_type == text: Select(ele).select_by_visible_text(content) else: case_logger.error("不撑持{},请确认Select的类型".format(select_type)) except Exception as e: case_logger.error("在{}上按照元素<{}>以{}方法进行下拉选择掉败!".format(img_doc, loc, select_type)) self.save_screenshot(img_doc) raise e def switch_to_windows(self, loc, img_doc, timeout=20, frequency=0.5): ‘‘‘ 窗口切换 :param loc: 元素定位的XPATH元组表达式 :param img_doc: 截图说明 :param timeout: 期待的超不时间 :param frequency: 轮询频率 :return: ‘‘‘ try: case_logger.info("在{}中按照元素<{}>进行窗口切换".format(img_doc, loc)) cur_handles = self.driver.window_handles # 获取点击之前的窗口总数 start_time = time.time() self.click_button(loc, img_doc, timeout, frequency) # 点击按钮后新的窗口呈现 WebDriverWait(self.driver, timeout, frequency).until(EC.new_window_is_opened(cur_handles)) wins = self.driver.window_handles # 再次获取窗口总数 self.driver.switch_to.window(wins[-1]) # 切换到新的页面 except Exception as e: case_logger.error("在{}中按照元素<{}>进行窗口切换掉败!".format(img_doc, loc)) self.save_screenshot(img_doc) raise e else: end_time = time.time() case_logger.info("在{}中按照元素<{}>进行窗口切换,期待时间:{}秒". format(img_doc, loc, round(end_time - start_time, 2)))

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/30926.html