| | |
| | | from selenium.common import TimeoutException |
| | | import importlib |
| | | import time |
| | | |
| | | from selenium.common.exceptions import StaleElementReferenceException, ElementClickInterceptedException |
| | | from selenium.webdriver.remote.webelement import WebElement |
| | | from selenium.webdriver.support.wait import WebDriverWait |
| | | from selenium.webdriver.support import expected_conditions as EC |
| | | from selenium.webdriver.remote.webdriver import WebDriver |
| | | |
| | | SimpleActions = ['clear()', 'send_keys()', 'click()', 'submit()', 'size', 'text', 'is_displayed()', 'get_attribute()'] |
| | | complexActions = ['iframe()', 'select()', 'option()'] |
| | | |
| | | # 默认超时时间10秒 |
| | | DEFAULT_TIMEOUT = 10 |
| | | # 默认重试次数 |
| | | DEFAULT_RETRY = 30 |
| | | |
| | | |
| | | class BasePage: |
| | | |
| | | retry_number = 0 |
| | | |
| | | # 初始化方法 |
| | | def __init__(self, driver): |
| | | def __init__(self, driver: WebDriver): |
| | | """构造方法,传入webdriver""" |
| | | self.driver = driver |
| | | |
| | | # 元素定位 |
| | | def get_element(self, locator): |
| | | return self.driver.find_element(*locator) |
| | | # def _get_page_elem(self, elem): |
| | | # """获取定位元素的by,以及操作action""" |
| | | # for each in self.elements: |
| | | # if each['name'] == elem: |
| | | # self.loc = each['loc'] |
| | | # if each['action'] is not None: |
| | | # self.action = each['action'] |
| | | # else: |
| | | # self.action = None |
| | | # if 'optionsLoc' in each: |
| | | # self.optionsLoc = each['optionsLoc'] |
| | | # else: |
| | | # self.optionsLoc = None |
| | | # if 'wait' in each: |
| | | # self.wait = each['wait'] |
| | | # else: |
| | | # self.wait = None |
| | | # |
| | | # def oper_elem(self, elem, args=None): |
| | | # self._get_page_elem(elem) |
| | | # cmd = self._selenium_cmd('find_element', args) |
| | | # return eval(cmd) |
| | | # |
| | | # def oper_elems(self, elem, args=None): |
| | | # self._get_page_elem(elem) |
| | | # cmd = self._selenium_cmd('find_elements', args) |
| | | # return eval(cmd) |
| | | # |
| | | # def _selenium_cmd(self, find_type='find_element', args=None): |
| | | # """拼接selenium查找命令,查找单个元素时find为'find_element',多个元素时为'find_elements'""" |
| | | # cmd = 'self.driver.' + find_type + '(*self.loc)' |
| | | # if self.action: |
| | | # cmd = 'self.' + self.action |
| | | # if args: |
| | | # cmd = cmd[:-1] + 'args' + ')' |
| | | # return cmd |
| | | # |
| | | # def iframe(self): |
| | | # self.driver.switch_to.frame(self.driver.find_element(*self.loc)) |
| | | # |
| | | # def click(self): |
| | | # if self.wait: |
| | | # wait = WebDriverWait(self.driver, self.wait, 0.5) |
| | | # wait.until(EC.presence_of_element_located(self.loc)).click() |
| | | # else: |
| | | # self.driver.find_element(*self.loc).click() |
| | | # |
| | | # # 使用js语句点击 |
| | | # def click_js(self): |
| | | # item = self.driver.find_element(*self.loc) |
| | | # self.driver.execute_script("arguments[0].click();", item) |
| | | # |
| | | # def send_keys(self, text): |
| | | # wait = WebDriverWait(self.driver, 10, 0.5) |
| | | # wait.until(EC.presence_of_element_located(self.loc)).send_keys(text) |
| | | # |
| | | # def text(self): |
| | | # wait = WebDriverWait(self.driver, 10, 0.5) |
| | | # return wait.until(EC.presence_of_element_located(self.loc)).text |
| | | # |
| | | def select(self, select_loc, options_loc, item): |
| | | """ |
| | | 选择传入的选项 |
| | | :param select_loc: 选择框定位 |
| | | :param options_loc: 选项定位 |
| | | :param item: 选项 |
| | | :return: |
| | | """ |
| | | # 点击选择框对象 |
| | | self.click(select_loc, timeout=10) |
| | | # 获取所有选项 |
| | | options = self.get_eles(options_loc, timeout=10) |
| | | for option in options: |
| | | if option.text == item: |
| | | option.click() |
| | | break |
| | | # |
| | | # def value_js(self): |
| | | # """ |
| | | # 使用js语句获取value值 |
| | | # :return: |
| | | # """ |
| | | # # 等待对象 |
| | | # wait = WebDriverWait(self.driver, 10, 0.5) |
| | | # input_box = wait.until(EC.presence_of_element_located(self.loc)) |
| | | # input_value = self.driver.execute_script("return arguments[0].value", input_box) |
| | | # return input_value |
| | | # |
| | | # def option(self, text): |
| | | # """ |
| | | # 点击传入的选项 |
| | | # :param text: |
| | | # :return: |
| | | # """ |
| | | # wait = WebDriverWait(self.driver, 10, 0.5) |
| | | # wait.until(EC.presence_of_all_elements_located(self.loc)) |
| | | # options = self.driver.find_elements(*self.loc) |
| | | # for option in options: |
| | | # if option.text == text: |
| | | # option.click() |
| | | |
| | | # 多个元素定位 |
| | | def get_elements(self, locator): |
| | | return self.driver.find_elements(*locator) |
| | | # 元素定位 |
| | | |
| | | def goto(self, url): |
| | | """访问url""" |
| | | self.driver.get(url) |
| | | |
| | | def get_ele(self, loc, timeout=None) -> WebElement: |
| | | """ |
| | | 获取元素 |
| | | :param loc: 元素定位 |
| | | :param timeout: 超时时间 |
| | | :return: |
| | | """ |
| | | if timeout: |
| | | return self.wait_visible(loc, timeout) |
| | | else: |
| | | return self.driver.find_element(*loc) |
| | | |
| | | def get_eles(self, loc, timeout=None): |
| | | """ |
| | | 获取多个元素 |
| | | :param loc: 元素定位 |
| | | :param timeout: 超时时间 |
| | | :return: |
| | | """ |
| | | if timeout: |
| | | return self.wait_visible(loc, timeout=timeout, find_type="elements") |
| | | else: |
| | | return self.driver.find_elements(*loc) |
| | | |
| | | def clear(self, loc, timeout=None): |
| | | """ |
| | | 清除文本框内容 |
| | | :param loc: |
| | | :param timeout: |
| | | :return: |
| | | """ |
| | | ele = self.get_ele(loc, timeout=timeout) |
| | | ele.clear() |
| | | |
| | | def fill(self, loc, text, timeout=None): |
| | | """页面输入""" |
| | | |
| | | ele = self.get_ele(loc, timeout=timeout) |
| | | # 先清除文本框内容 |
| | | ele.clear() |
| | | # 填写内容 |
| | | ele.send_keys(text) |
| | | |
| | | def wait_visible(self, loc, timeout=DEFAULT_TIMEOUT, find_type="element") -> WebElement: |
| | | """ |
| | | 等待元素可见 |
| | | :param loc: 元素定位 |
| | | :param timeout: 等待时间 |
| | | :param find_type: 等待元素的类型 |
| | | :return: |
| | | """ |
| | | wait = WebDriverWait(self.driver, timeout=timeout) |
| | | element = None |
| | | if find_type == "element": |
| | | element = wait.until(EC.visibility_of_element_located(loc)) |
| | | elif find_type == "elements": |
| | | element = wait.until(EC.visibility_of_all_elements_located(loc)) |
| | | return element |
| | | |
| | | def click(self, loc, timeout=None): |
| | | """ |
| | | 点击元素 |
| | | :param loc: 元素定位 |
| | | :param timeout: 超时时间 |
| | | :return: |
| | | """ |
| | | try: |
| | | if timeout: |
| | | ele = self.wait_clickable(loc, timeout=timeout) |
| | | ele.click() |
| | | else: |
| | | ele = self.driver.find_element(*loc) |
| | | ele.click() |
| | | self.retry_number = 0 |
| | | except (StaleElementReferenceException, ElementClickInterceptedException): |
| | | if self.retry_number >= DEFAULT_RETRY: |
| | | return |
| | | time.sleep(1) |
| | | self.retry_number += 1 |
| | | self.click(loc, timeout=timeout) |
| | | |
| | | def click_js(self, loc, timeout=None): |
| | | """ |
| | | JavaScript点击元素 |
| | | :param loc: |
| | | :param timeout: |
| | | :return: |
| | | """ |
| | | item = self.get_ele(loc, timeout=timeout) |
| | | self.driver.execute_script("arguments[0].click();", item) |
| | | |
| | | def wait_clickable(self, loc, timeout=DEFAULT_TIMEOUT) -> WebElement: |
| | | """ |
| | | 等待元素可点击 |
| | | :param loc: 元素定位 |
| | | :param timeout: 超时时间 |
| | | :return: |
| | | """ |
| | | wait = WebDriverWait(self.driver, timeout=timeout) |
| | | element = wait.until(EC.element_to_be_clickable(loc)) |
| | | return element |
| | | |
| | | def equals(self, loc, text): |
| | | """ |
| | | 判断元素的value或者text是否与text相等 |
| | | :param loc: |
| | | :param text: |
| | | :return: |
| | | """ |
| | | # 先获取value |
| | | ele_value = self.get_ele(loc, timeout=10).get_attribute("value") |
| | | # 如果为None则通过value_js获取value值 |
| | | if not ele_value: |
| | | ele_value = self.get_value_js(loc, timeout=10) |
| | | # 如果还为空则获取text |
| | | if not ele_value: |
| | | ele_value = self.get_ele(loc, timeout=10).text |
| | | return ele_value == text |
| | | |
| | | def contains(self, loc, text): |
| | | """ |
| | | 判断元素的value或者text包含text |
| | | :param loc: |
| | | :param text: |
| | | :return: |
| | | """ |
| | | # 先获取value |
| | | ele_value = self.get_ele(loc).get_attribute("value") |
| | | # 如果为None则通过value_js获取value值 |
| | | if not ele_value: |
| | | ele_value = self.get_value_js(loc) |
| | | # 如果还为空则获取text |
| | | if not ele_value: |
| | | ele_value = self.get_ele(loc).text |
| | | return text in ele_value |
| | | |
| | | # 多个元素定位 |
| | | def get_elements_wait(self, locator): |
| | |
| | | wait.until(EC.presence_of_element_located(locator)) |
| | | return self.driver.find_element(*locator) |
| | | |
| | | # 使用js语句点击 |
| | | def script_click(self, *locator): |
| | | item = self.get_element(*locator) |
| | | self.driver.execute_script("arguments[0].click();", item) |
| | | |
| | | def script_click_wait(self, *locator): |
| | | def click_js_wait(self, *locator): |
| | | item = self.get_element_wait(*locator) |
| | | self.driver.execute_script("arguments[0].click();", item) |
| | | |
| | | # 点击 |
| | | def click(self, locator): |
| | | def click_element_js(self, element): |
| | | """ |
| | | 点击元素 |
| | | :param locator: 元素定位 |
| | | 使用js点击元素 |
| | | :param element: 要点击的元素 |
| | | :return: |
| | | """ |
| | | self.get_element(locator).click() |
| | | self.driver.execute_script("arguments[0].click();", element) |
| | | |
| | | # # 点击 |
| | | # def click(self, locator): |
| | | # """ |
| | | # 点击元素 |
| | | # :param locator: 元素定位 |
| | | # :return: |
| | | # """ |
| | | # self.get_element(locator).click() |
| | | |
| | | def click_wait(self, *locator): |
| | | self.get_element_wait(*locator).click() |
| | | |
| | | # 输入 |
| | | def send_text(self, text, locator): |
| | | """ |
| | | 输入内容 |
| | | :param text: 内容 |
| | | :param locator: 元素定位 |
| | | :return: |
| | | """ |
| | | self.get_element(locator).send_keys(text) |
| | | # # 输入 |
| | | # def fill(self, text, locator): |
| | | # """ |
| | | # 输入内容 |
| | | # :param text: 内容 |
| | | # :param locator: 元素定位 |
| | | # :return: |
| | | # """ |
| | | # self.get_element(locator).send_keys(text) |
| | | |
| | | def send_text_wait(self, text, *locator): |
| | | self.get_element_wait(*locator).send_keys(text) |
| | | |
| | | # JavaScript获取元素值 |
| | | def get_input_value_js(self, locator): |
| | | input_box = self.get_element(locator) |
| | | input_value = self.driver.execute_script("return arguments[0].value", input_box) |
| | | return input_value |
| | | def get_value_js(self, loc, timeout=None): |
| | | """ |
| | | 执行JavaScript获取value值 |
| | | :param timeout: |
| | | :param loc: |
| | | :return: |
| | | """ |
| | | ele = self.get_ele(loc, timeout=timeout) |
| | | value = self.driver.execute_script("return arguments[0].value", ele) |
| | | return value |
| | | |
| | | def get_input_value_js_wait(self, *locator): |
| | | input_box = self.get_element_wait(*locator) |
| | |
| | | self.get_element_wait(*locator).clear() |
| | | |
| | | # 表单切换 |
| | | def switch_iframe(self, locator): |
| | | self.driver.switch_to.frame(self.get_element(locator)) |
| | | def switch_iframe(self, loc): |
| | | """ |
| | | 切换表单 |
| | | :param loc: 表单定位 |
| | | :return: |
| | | """ |
| | | # 获取到iframe元素 |
| | | iframe = self.get_ele(loc, timeout=10) |
| | | self.driver.switch_to.frame(iframe) |
| | | |
| | | # 切换到上一层的iframe |
| | | def switch_parent_iframe(self): |
| | | """ |
| | | 切换到上一层的iframe |
| | | :return: |
| | | """ |
| | | self.driver.switch_to.parent_frame() |
| | | |
| | | def switch_iframe_wait(self, locator): |
| | |
| | | e = wait.until(EC.element_to_be_clickable(locator)) |
| | | if e is not None: |
| | | return True |
| | | except TimeoutException: |
| | | except: |
| | | pass |
| | | return False |
| | | |
| | |
| | | e = wait.until(EC.presence_of_element_located(locator)) |
| | | if e is not None: |
| | | return True |
| | | except TimeoutException: |
| | | except: |
| | | pass |
| | | return False |
| | | |
| | |
| | | """截取当前窗口保存为图片""" |
| | | return self.driver.get_screenshot_as_png() |
| | | |
| | | def open_new_table_to_url(self, url): |
| | | def goto_new_table(self, url): |
| | | """ |
| | | 打开一个新的标签页,并跳转到指定的url |
| | | :return: |
| | |
| | | self.switch_window(-1) |
| | | # 在新标签页中加载指定url |
| | | self.driver.get(url) |
| | | |
| | | def elements_is_visibility(self, locator): |
| | | """ |
| | | 判断是否至少有一个元素在页面中可见 |
| | | :param locator: |
| | | :return: |
| | | """ |
| | | wait = WebDriverWait(self.driver, 10, 0.5) |
| | | return wait.until(EC.visibility_of_any_elements_located(locator)) |
| | | |
| | | def add_elements(self, ele): |
| | | """ |
| | | 在elements中新增元素 |
| | | :param ele: |
| | | :return: |
| | | """ |
| | | self.elements.append(ele) |
| | | |
| | | |
| | | def get_page_elements(page): |
| | | """ |
| | | 动态加载页面定义文件,获取文件中定义的元素列表elements |
| | | :param page: |
| | | :return: |
| | | """ |
| | | elements = None |
| | | if page: |
| | | try: |
| | | m = importlib.import_module(page) |
| | | elements = m.elements |
| | | except Exception as e: |
| | | pass |
| | | return elements |