UI界面自动化BagePage

这篇具有很好参考价值的文章主要介绍了UI界面自动化BagePage。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

常用basepage模块代码

# -*- coding: utf-8 -*-
# @Desc: UI自动化测试的一些基础浏览器操作方法

# 第三方库导入
import time
from logging import config
import random

import allure
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.select import Select

import config
from common.utils.ReturnTime import ReturnTime
from jc_log.setting import get_logger
import pyautogui
from pywinauto.keyboard import send_keys
from selenium.common.exceptions import NoSuchElementException, InvalidSelectorException, TimeoutException
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait

logger = get_logger(__name__)
g_timeout = 10
g_poll_frequency = 0.2


class BasePage:
    """
    UI自动化基础操作封装
    """

    def __init__(self, driver):
        self.driver = driver
        self.__img_dir = config.REPORT_DIR

    def refresh(self):
        """刷新网页"""
        self.driver.refresh()

    def get_url(self, url):
        """
        访问指定地址
        """
        self.driver.get(url=url)
        return self.driver.current_url

    def get_current_url(self):
        """
        获取当前浏览器驱动的地址
        """
        return self.driver.current_url

    def force_click(self, locator: tuple, mode: str = "click", force=False):
        """鼠标点击,当元素不可点击的时候,使用强制点击

        :param locator: 元素定位,元祖类型
        :param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在),click(元素可点击)
        :param force: 强制点击,默认false
        """
        try:
            elem = self.find_element(locator=locator, mode=mode)
            if not force:
                self.driver.execute_script("arguments[0].click()", elem)
            else:
                elem.click()
                self.driver.execute_script("arguments[0].click({force: true})", elem)
        except Exception as e:
            print("未找到元素:{}".format(e))
            raise e

    def wait_element_visibility(self, locator: tuple, timeout=20, poll_frequency=g_poll_frequency):
        """
        显性等待: 等待元素可见

        :param locator: 元素定位,元祖类型
        :param timeout
        :param poll_frequency
        :return:
        """
        page = self.get_current_url()
        logger.debug(f"-开始-等待页面{page}的元素:{locator}可见")
        try:
            # 获取等待开始时间的时间戳
            __start_time = ReturnTime.get_timestamp()
            rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(ec.visibility_of_element_located(locator))
            # 计算元素等待的时间
            __wait_time = ReturnTime.get_timestamp() - __start_time
            logger.debug(f"页面:{page}上的元素{locator}已可见,共计等待{__wait_time:0.2f}秒")
        except TimeoutException:
            logger.error(f"页面:{page},等待元素{locator}超时")
            self.set_error_img()
            raise TimeoutException('元素等待超时')
        except InvalidSelectorException as e:
            logger.error(f"页面:{page},元素不可见或定位表达式:{locator}异常\n {e}")
            raise InvalidSelectorException('元素定位异常')
        return rtn

    def wait_element_clickable(self, locator: tuple, timeout=g_timeout, poll_frequency=g_poll_frequency):
        """
        显性等待: 等待元素可点击

        :param locator: 元素定位,元祖类型
        :param timeout:
        :param poll_frequency
        :return:
        """

        page = self.get_current_url()
        logger.debug(f"-开始-等待页面{page}的元素:{locator}可点击")
        try:
            # 获取等待开始时间的时间戳
            __start_time = ReturnTime.get_timestamp()
            rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(
                ec.element_to_be_clickable(locator))

            # 计算元素等待的时间
            __wait_time = ReturnTime.get_timestamp() - __start_time
            logger.debug(f"页面:{page}上的元素{locator}已可点击,共计等待{__wait_time:0.2f}秒")
        except TimeoutException as e:
            logger.error(f"页面:{page},等待元素{locator}超时")
            self.set_error_img()
            raise e
        except InvalidSelectorException as e:
            logger.error(f"页面:{page},元素不可点击或定位表达式:{locator}异常\n {e}")
            raise e
        return rtn

    def wait_element_presence(self, locator: tuple, timeout=g_timeout, poll_frequency=g_poll_frequency):
        """
        显性等待: 等待元素被加载出来

        :param locator: 元素定位,元祖类型
        :param timeout
        :param poll_frequency
        :return:
        """
        page = self.get_current_url()
        logger.debug(f"-开始-等待页面{page}的元素:{locator}存在")
        try:
            # 获取等待开始时间的时间戳
            __start_time = ReturnTime.get_timestamp()
            rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(
                ec.presence_of_all_elements_located(locator))
            # 计算元素等待的时间
            __wait_time = ReturnTime.get_timestamp() - __start_time
            logger.debug(f"页面:{page}上的元素{locator}已存在,共计等待{__wait_time:0.2f}秒")
        except TimeoutException as e:
            logger.error(f"页面:{page},等待元素{locator}超时")
            self.set_error_img()
            raise e
        except InvalidSelectorException as e:
            logger.error(f"页面:{page},元素不存在或定位表达式:{locator}异常\n {e}")
            raise e
        return rtn

    def wait_element_not_visible(self, locator: tuple, timeout=g_timeout, poll_frequency=g_poll_frequency):
        """
        等待元素不可见

        :param locator: 元素定位表达式
        :param timeout
        :param poll_frequency
        :return:
        :return: 无返回值
        """
        page = self.get_current_url()
        logger.debug(f"-开始-等待页面{page}的元素:{locator}存在")
        try:
            # 获取等待开始时间的时间戳
            __start_time = ReturnTime.get_timestamp()
            time.sleep(1)
            rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(
                ec.invisibility_of_element_located(locator))
            # 计算元素等待的时间
            __wait_time = ReturnTime.get_timestamp() - __start_time
            logger.debug(f"页面:{page}上的元素{locator}已经不可见,共计等待{__wait_time:0.2f}秒")
        except TimeoutException as e:
            logger.error(f"页面:{page},等待元素{locator}不可见超时")
            self.set_error_img()
            raise e
        except InvalidSelectorException as e:
            logger.error(f"页面:{page},元素不存在或定位表达式:{locator}异常\n {e}")
            raise e
        return rtn

    def get_element_attribute(self, locator: tuple, attr_name):
        """
        获取元素属性值

        :param locator: 元素定位,元祖类型
        :param attr_name
        :return: 元素属性值
        """
        try:
            return self.driver.find_element(*locator).get_attribute(attr_name)
        except NoSuchElementException as e:
            print("未找到元素:{}".format(e))
            raise e

    def get_name(self, locator: tuple):
        """
        获取元素的name属性值
        """
        return self.get_element_attribute(locator, "name")

    def get_title(self, locator: tuple):
        """
        获取元素的title属性值
        """
        return self.get_element_attribute(locator, "title")

    def get_class(self, locator: tuple):
        """
        获取元素的class属性值
        """
        return self.get_element_attribute(locator, "class")

    def switch_to_frame(self, reference=None, timeout=g_timeout, poll=g_poll_frequency):
        """
        iframe切换

        :param reference: 可以是id, name,索引或者元素定位(元祖)
        :param timeout:
        :param poll:
        :return:
        """
        if not reference:
            return self.driver.switch_to.default_content()
        return WebDriverWait(self.driver, timeout, poll).until(
            ec.frame_to_be_available_and_switch_to_it(reference)
        )

    def __get_title_handle(self, title):
        handles = self.driver.window_handles
        for handle in handles:
            self.driver.switch_to.window(handle)
            if self.driver.title == title:
                return handle

    def switch_to_window(self, title):
        """切换到指定窗口"""
        self.__get_title_handle(title)
        return self

    def switch_next_window(self):
        """切换到另一个窗口"""
        # 获取所有的窗口
        windows = self.driver.window_handles
        if len(windows) >= 2:
            # 切换窗口
            self.driver.switch_to.window(self.driver.window_handles[-1])
        return self

    def open_new_window(self, url):
        """打开一个新窗口"""
        # 获取所有的窗口
        start_window = self.driver.window_handls
        # 打开新窗口
        js = "window.open({})".format(url)
        self.driver.execute_script(js)
        # 等待新窗口出现,进行切换
        WebDriverWait(self.driver, 5, 0.5).until(
            ec.new_window_is_opened(start_window)
        )
        # 切换窗口
        self.driver.switch_to.window(self.driver.window_handls[-1])
        return self

    def __select_wait_method(self, locator: tuple, mode: str = "visible") -> None:
        """
        选择元素定位的等待方式

        :param locator: 元素的定位表达式 例:(By.xx,'定位表达式')
        :param mode: visible(元素可见), exist(元素存在),click(元素可点击)
        :return: 无返回值
        """
        page = self.get_current_url()
        if mode == "visible":
            self.wait_element_visibility(locator=locator)
        elif mode == "exist":
            self.wait_element_presence(locator=locator)
        elif mode == "click":
            self.wait_element_clickable(locator=locator)
        else:
            logger.error(f"定位{page}页面的元素:{locator},mode参数传值异常,入参值为:{mode}")

    def find_element(self, locator: tuple, mode: str = "visible") -> WebElement:
        """
        定位元素,支持所有定位单个元素的定位表达式

        :param locator: 元素的定位表达式 例:(By.xx,'定位表达式')
        :param mode: visible(元素可见), exist(元素存在),click(元素可点击)
        :return: 定位到的元素对象
        """
        page = self.get_current_url()
        self.__select_wait_method(locator=locator, mode=mode)
        try:
            logger.debug(f"正在定位{page}页面的: {locator} 的元素")
            element = self.driver.find_element(*locator)
            self.element_dyeing(element=element)
            return element
        except TimeoutException:
            logger.error(f"页面:{page},定位元素:{locator}定位超时")
            self.set_error_img()
            raise TimeoutException("元素定位超时请检查")
        except Exception:
            logger.error(f"页面:{page},定位元素:{locator}定位失败")
            self.set_error_img()
            raise Exception("元素定位失败请检查")

    def find_elements(self, locator: tuple, mode: str = "visible") -> list:
        """
        定位一组元素,返回一个列表

        :param locator: 元素的定位表达式 例:(By.xx,'定位表达式')
        :param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在)
        :return: 返回一组元素是一个列表
        """
        page = self.get_current_url()
        self.__select_wait_method(locator=locator, mode=mode)
        try:
            logger.debug(f"正在定位{page}页面的: {locator} 的元素")
            element_list = self.driver.find_elements(*locator)
            return element_list
        except NoSuchElementException as e:
            logger.error(f"页面:{page},定位元素:{locator}定位失败")
            self.set_error_img()
            raise e

    def __move_element_visible(self, locator: tuple, element: WebElement, alignment: bool = False) -> None:
        """
         将元素移动到页面可见区域

        :param locator: 元素的定位表达式 例:(By.xx,'定位表达式')
        :param alignment 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param element 需要可见的元素
        :return: 无返回值
        """
        page = self.get_current_url()
        logger.debug(f'将{page}页面的元素:{locator}移动至浏览器可见区域')
        try:
            # 代码执行比页面渲染速度快 这里放0.5秒等待页面渲染
            time.sleep(0.5)
            self.driver.execute_script('arguments[0].scrollIntoView({0});'.format(alignment), element)
            # 休眠1秒让页面可以正常滚动到对应的位置再执行下去
            time.sleep(1)
        except Exception as e:
            logger.error(f"{page}页面的元素:{locator}移动失败\n{e}")
            self.set_error_img()
            raise e

    def click(self, locator: tuple, mode: str = "click", alignment: bool = False, move_element: bool = False,
              is_double_click: bool = False) -> None:
        """
        点击元素

        :param locator: 元素的定位表达式 例:(By.xx,'定位表达式')
        :param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在),click(元素可点击)
        :param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        :param is_double_click: False单击元素,传入True 双击元素
        :return: 无返回值
        """
        page = self.get_current_url()
        element = self.find_element(locator=locator, mode=mode)
        if move_element is True:
            self.__move_element_visible(locator=locator, element=element, alignment=alignment)
        try:
            logger.debug(f"点击:{page}页面,属性为{locator}的元素")
            if is_double_click:
                ActionChains(self.driver).double_click(element).perform()
            else:
                element.click()
        except Exception as e:
            logger.error(f"页面{page}的元素: {locator} 点击失败")
            self.set_error_img()
            raise e

    def click_elements(self, locator: tuple, mode: str = "click", alignment: bool = False, move_element: bool = False,
                       is_double_click: bool = False) -> None:
        """
        点击一组元素

        :param locator: 元素的定位表达式 例:(By.xx,'定位表达式')
        :param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在),click(元素可点击)
        :param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        :param is_double_click: False单击元素,传入True 双击元素
        :return: 无返回值
        """
        page = self.get_current_url()
        elements = self.find_elements(locator=locator, mode=mode)
        if move_element is True:
            self.__move_element_visible(locator=locator, element=elements[0], alignment=alignment)
        try:
            logger.debug(f"点击:{page}页面,属性为{locator}的元素")
            for element in elements:
                if is_double_click:
                    ActionChains(self.driver).double_click(element).perform()
                else:
                    element.click()
        except Exception as e:
            logger.error(f"页面{page}的元素: {locator} 点击失败")
            self.set_error_img()
            raise e

    def random_click_element(self, locator: tuple, num: int, mode: str = "click", alignment: bool = False,
                             move_element: bool = False) -> str:
        """
        随机点击一个元素

        :param locator: 元素的定位表达式 例:(By.xx,'定位表达式')
        :param num: 从第几位元素开始点击
        :param mode: visible(元素可见), exist(元素存在),click(元素可点击)
        :param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        :return: 点击的元素的文本
        """
        page = self.get_current_url()
        elements = self.find_elements(locator=locator, mode=mode)
        click_num: int = random.randint(num, len(elements) - 1)
        try:
            element = elements[click_num]
            if move_element is True:
                self.__move_element_visible(locator=locator, element=element, alignment=alignment)
            self.element_dyeing(element)
            logger.debug(f"点击:{page}页面,属性为{locator}的元素中的{click_num}位")
            element.click()
        except Exception as e:
            logger.error(f"页面{page}的元素: {locator} 中的第{click_num}位元素点击失败")
            self.set_error_img()
            raise e
        return element.text

    def input_text(self, locator: tuple, content: str or int, mode: str = "visible", alignment: bool = False,
                   move_element: bool = False) -> WebElement:
        """
        输入文本内容

        :param locator: 传入元素定位表达式
        :param content: 传入输入的文本内容
        :param mode:  visible(元素可见), exist(元素存在)
        :param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        :return: 无返回值
        """
        page = self.get_current_url()
        element = self.find_element(locator=locator, mode=mode)
        if move_element is True:
            self.__move_element_visible(locator=locator, element=element, alignment=alignment)
        try:
            self.clear_contents(locator=locator, mode=mode, alignment=alignment)
            logger.debug(f"输入操作:{page}页面下的属性为:{locator}的元素,输入内容为{content}")
            element.send_keys(content)
            self.driver.execute_script(
                "arguments[0].setAttribute('style', 'background: write; border: 1px solid black;');", element)
        except Exception as e:
            self.set_error_img()
            logger.error(f"页面{page}的属性: {locator} 输入操作失败")
            raise e
        return element

    def clear_contents(self, locator: tuple, mode: str = "visible", alignment: bool = False,
                       move_element: bool = False) -> None:
        """
        清除文本内容

        :param locator: 传入元素定位表达式
        :param mode:  visible(元素可见), exist(元素存在)
        :param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        :return: 无返回值
        """
        page = self.get_current_url()
        element = self.find_element(locator=locator, mode=mode)
        if move_element is True:
            self.__move_element_visible(locator=locator, element=element, alignment=alignment)
        try:
            logger.debug(f"输入操作:{page}页面下的属性为:{locator}的元素,清除内容")
            # 保证正常清除
            time.sleep(0.2)
            element.clear()
        except Exception as e:
            self.set_error_img()
            logger.error(f"页面{page}的属性: {locator} 清除操作失败")
            raise e

    def get_element_text(self, locator: tuple, mode: str = 'visible', alignment: bool = False,
                         move_element: bool = False) -> str:
        """
        获取元素的文本内容

        :param locator:  传入元素定位表达式
        :param mode: visible(元素可见), exist(元素存在)
        :param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        :return: 返回获取到的元素文本内容
        """
        page = self.get_current_url()
        element = self.find_element(locator=locator, mode=mode)
        if move_element is True:
            self.__move_element_visible(locator=locator, element=element, alignment=alignment)
        try:
            logger.debug(f"文本获取操作:获取{page}页面下的属性为:{locator}的元素的文本内容")
            return element.text
        except Exception as e:
            logger.error(f"页面{page}的元素:{locator}获取文本操作失败")
            self.set_error_img()
            raise e

    def click_radios(self, locator: tuple, method: str, amount: int = None, mode: str = 'visible',
                     alignment: bool = False, move_element: bool = False) -> WebElement:
        """
        复选框内容点击

        :param locator: 传入元素定位表达式
        :param mode:  visible(元素可见), exist(元素存在)
        :param amount: 传入复选项的数量 例子如果是3个选项就传入3
        :param method: 选择对应的内容选择方式 all 点击复选框的全部内容 random 随机点击复选框的中的某一个选项 assign点击指定的某个复选项
        :param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        :return: 全部点击时无返回,其他返回被点击的元素
        """
        # 定位到复选框一定是一组元素
        page = self.get_current_url()
        elements: list[WebElement] = self.find_elements(locator=locator, mode=mode)
        try:
            logger.debug('点击方式为:{}'.format(method))
            if method == 'all':
                # 点击复选项中每一个元素
                for ele in elements:
                    if move_element is True:
                        self.__move_element_visible(locator=locator, element=ele, alignment=alignment)
                    ele.click()
            # 随机点击复选项中的某一个内容
            elif method == 'random':
                # 导入随机数包
                import random
                # 生成指定范围之内的随机数作为需要点击的radio
                num = random.randint(0, amount - 1)
                element = elements[num]
                if move_element is True:
                    self.__move_element_visible(locator=locator, element=element, alignment=alignment)
                element.click()
                # 返回被点击的元素
                return element
            # 点击复选框中指定位置的选项
            elif method == 'assign':
                # 因为从0开始计数,所以传入的 amount-1
                element = elements[amount - 1]
                if move_element is True:
                    self.__move_element_visible(locator=locator, element=element, alignment=alignment)
                element.click()
                return element
            else:
                logger.error('点击方式输入错误,请检查')
        except Exception as e:
            logger.error(f"页面{page}的元素:{locator}复选框点击操作失败")
            self.set_error_img()
            raise e

    @staticmethod
    def element_is_selected(element: WebElement):
        """
        判断元素是否勾选

        :param element: 需要校验是否勾选的元素
        :return: 选中是Ture 没有选择是False
        """
        return element.is_selected()

    def select_contents_menu(self, locator: tuple, text: str, mode: str = 'visible', alignment: bool = False,
                             move_element: bool = False) -> None:

        """
        选择下拉菜单中的内容

        :param locator: 传入元素定位表达式
        :param text: 出入下拉列表需要选择的内容
        :param mode: visible(元素可见), exist(元素存在)
        :param alignment:  默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐
        :param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用
        """
        page = self.get_current_url()
        element = self.find_element(locator=locator, mode=mode)
        # 定义一个存储菜单内容的空列表
        option = []
        if move_element is True:
            self.__move_element_visible(locator=locator, element=element, alignment=alignment)
        try:
            # 获取下拉列表的内容
            options = element.find_elements_by_tag_name("option")
            for value in options:
                option.append(value)
            if text in option:
                Select(element).select_by_visible_text(text)
            else:
                logger.error(f"选项:{text}不在下拉列表之中请检查")
        except Exception as e:
            self.set_error_img()
            logger.error(f"页面{page}的元素:{locator}下拉框操作失败请检查")
            raise e

    def dispose_alert(self, action: str) -> str:
        """
        处理页面alert

        :param action: 参数为 accept 点击alert的确定 dismiss点击alert的取消
        :return: 返回alert的文本内容 可能有些用例需要用这个参数去校验
        """
        # 等待alert出现再去操作
        WebDriverWait(self.driver, 5, 0.5).until(ec.alert_is_present())
        alert: Alert = self.driver.switch_to.alert
        # 尝试点击alert
        try:
            if action == 'accept':
                alert.accept()
            elif action == 'dismiss':
                alert.dismiss()
            else:
                logger.error('alert 处理参数错误请检查')
            return alert.text
        except Exception as e:
            logger.error('alert处理异常')
            raise e

    def get_text(self, locator: tuple):
        """
        获取元素的文本值

        :param locator: 元素定位
        :return:
        """
        try:
            elem = self.driver.find_element(*locator)
            value = elem.text
            return value
        except NoSuchElementException as e:
            print(f"get未找到元素{e}")
            raise e

    def element_dyeing(self, element) -> None:
        """
        将被操作的元素染色

        :return: None
        """
        self.driver.execute_script("arguments[0].setAttribute('style', 'background: yellow; border: 2px solid red;');",
                                   element)

    def set_error_img(self) -> None:
        """
        截图

        :return: None
        """
        __time_tag = ReturnTime.get_timestamp()
        __img_path = self.__img_dir + f"/{__time_tag}.png"
        try:
            # 进行截图
            self.driver.save_screenshot(filename=__img_path)
            logger.error(f"截图成功文件名称为:{__time_tag}.png")
            __file = open(__img_path, "rb").read()
            allure.attach(__file, "用例执行失败截图", allure.attachment_type.PNG)
        except Exception as e:
            logger.error(f"执行失败截图未能正确添加进入测试报告:{e}")
            raise e

    def set_case_img(self) -> None:
        """
        用例执行完毕截图,并且将截图加入allure测试报告中

        :return: 无返回值
        """
        with allure.step("关键步骤截图"):
            __img_name = ReturnTime.get_timestamp()
            __img_path = self.__img_dir + f"/{__img_name}.png"
            try:
                # 截图前等待1秒防止图片没有正常加载
                time.sleep(1)
                self.driver.save_screenshot(filename=__img_path)
                logger.debug(f"用例执行完成,截图成功,文件名称为{__img_name}.png")
                # 读取图片信息
                __file = open(file=__img_path, mode="rb").read()
                allure.attach(__file, "关键步骤截图", allure.attachment_type.PNG)
            except Exception as e:
                logger.error(f"测试结果截图,未能正确添加进入测试报告:{e}")
                raise e

    # ------------------------ START: JS事件 ------------------------ #
    def execute_js(self, js, *args):
        """
        执行javascript脚本
        js: 元组形式参数
        """
        self.driver.execute_script(js, *args)
        return self

    def upload_file_pywinauto(self, file_path):
        """
        使用pywinauto来上传
            缺点:只能在windows上使用。
            优点:可以选择多个文件,路径中有中文也可以。
            安装:pip install pywinauto -i https://mirrors.aliyun.com/pypi/simple/
        :param file_path: 文件绝对路径,支持传数组
        """
        if isinstance(file_path, list):
            for path in file_path:
                # 上传文件
                send_keys(path)
        else:
            # 上传文件
            send_keys(file_path)
        # 点击回车
        send_keys("{VK_RETURN}")
        return self

    def upload_file_pyautogui(self, file_path):
        """
        使用pyautogui来上传
            缺点:只能选择一个文件,路径中有中文会出问题。
            优点:跨平台。Linux, mac,windows都可以。
            安装:pip install pyautogui -i https://mirrors.aliyun.com/pypi/simple/
        :param file_path: 文件绝对路径,支持传数组
        """
        if isinstance(file_path, list):
            print("只能选择一个文件,默认选择第一个")
            file_path = file_path[0]

        # 上传文件
        pyautogui.write(file_path)
        # 点击回车
        pyautogui.press("enter", 2)
        return self

    # ------------------------ END: JS事件 ------------------------ #

    # ------------------------ START: 鼠标事件:双击,悬停,拖动 ------------------------ #

    def double_click(self, locator):
        """
        鼠标双击
        :param locator:
        :return:
        """
        try:
            elem = self.driver.find_element(*locator)
            action = ActionChains(self.driver)
            action.double_click(elem).perform()
            return self
        except NoSuchElementException as e:
            print("未找到元素:{}".format(e))
            raise e

    def drag_and_drop(self, start_locator, end_locator):
        """鼠标拖动"""
        elem_start = self.driver.find_element(*start_locator)
        elem_end = self.driver.find_element(*end_locator)
        action = ActionChains(self.driver)
        action.double_click((elem_start, elem_end)).perform()
        return self

    def hover(self, locator):
        """鼠标悬停"""
        el = self.driver.find_element(*locator)
        action = ActionChains(self.driver)
        action.move_to_element(el).perform()
        return self

文章来源地址https://www.toymoban.com/news/detail-696563.html

到了这里,关于UI界面自动化BagePage的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零搭建完整python自动化测试框架(UI自动化和接口自动化

    总体框架 PO模式、DDT数据驱动、驱动 框架技术选择 框架运行结果 各用例对应的定义方式(PO/DDT) 测试执行结果 从零开始搭建项目 一、开发环境搭建 二、新建项目 三、基础功能实现 1. 配置功能实现(Conf) 2. 日志功能实现(Log) 3. 读取EXCEL实现(data) 4. 邮件发送实

    2024年02月07日
    浏览(53)
  • 从零搭建完整python自动化测试框架(UI自动化和接口自动化)

    总体框架 PO模式、DDT数据驱动、驱动 框架技术选择 框架运行结果 各用例对应的定义方式(PO/DDT) 测试执行结果 从零开始搭建项目 一、开发环境搭建 二、新建项目 三、基础功能实现 1. 配置功能实现(Conf) 2. 日志功能实现(Log) 3. 读取EXCEL实现(data) 4. 邮件发送实

    2024年02月04日
    浏览(50)
  • Python的ui自动化框架搭建

    目录 一、web项目框架搭建 1.1 项目结构 1.2 代码 1.2.1 项目配置文件 1.2.2 入口文件编写 1.2.3 日志模块内容编写 1.2.4 测试用例的编写 1.3 总结 二、夹具(脚手架)的抽取和使用 2.1 共享夹具的使用 2.1.1 共享夹具的定义 2.1.2 登录模块夹具的使用 2.2 混合夹具的使用 2.3 测试用例基

    2024年02月16日
    浏览(38)
  • 【UI自动化测试技术】自动化测试研究:Python+Selenium+Pytest+Allure,详解UI自动化测试,学习模拟鼠标+模拟键盘进行相关操作(精)(四)

    1、了解元素交互的常用方法 2、学习如何对多选元素进行操作 3、 学习模拟鼠标进行相关操作 ( 本节目标 ) 4、 学习模拟键盘进行相关操作 ( 本节目标 ) 用于向 Web 浏览器提供虚拟化设备输入操作的低级接口.除了刚刚讲过的Web元素交互之外, Actions 接口 还提供了对指定输

    2024年03月24日
    浏览(44)
  • python+selenium实现UI自动化(一)

    selenium官方网站 selenium ide 录制工具。 火狐/google/edge插件 selenium webdriver   结合代码来编写自动化用例。提供很多在浏览器上的操作的api,本文主要记录此项的学习过程 selenium grid   分布式。火狐/google/edge上同时运行。把所有用例拆分到多设备上运行,运行效率更高,更快。

    2023年04月24日
    浏览(33)
  • python+selenium封装UI自动化框架

    seleinum框架 框架的思想: 解决我们测试过程中的问题:大量的重复步骤,用自动化来实现 1)配置和程序的分离 2)测试数据和程序的分离 3)不懂编程的人员可以方便使用:使用的时候不需要写程序 4)有日志功能,实现无人值守 5)自动发报告 6)框架中不要有重复的代码,

    2024年02月09日
    浏览(49)
  • 【AI Programming 】使用AI大模型来自动化生成DSL代码、RPC-SQL代码和UI Component 用户界面

    在当今的时代,随着人工智能技术的不断发展,越来越多的开发者开始探索低代码开发的领域。低代码开发可以让开发者更加高效地开发软件,减少重复性劳动,提高开发效率。在本文中,我们将介绍如何结合低代码开发和ChatGPT技术实现一个高效的开发流程。

    2024年02月13日
    浏览(43)
  • python零基础到实现UI自动化 (1)

            最近开始在研究selenium了,主要是发现性能测试比较局限于环境因此JMeter也停留在比较简单的接口测试环境下类似就和postman那样像功能测试工具一样,没有更深入学习的意义了。不过学习不能停滞不前,正好满足我的码字欲望的同时也要复习一下python的部分,毕竟代

    2023年04月11日
    浏览(22)
  • python ui自动化测试元素定位常用语法

    第一部分是css样式定位方法 选择器 示例 示例说明 CSS . class .intro 选择所有class=\\\"intro\\\"的元素 1 # id #firstname 选择所有id=\\\"firstname\\\"的元素 1 * * 选择所有元素 2 element p 选择所有p元素 1 element,element div,p 选择所有div元素和p元素 1 element   element div p 选择div元素内的所有p元素 1 element

    2024年02月13日
    浏览(35)
  • Python UI自动化-Selenium【JS操作】

    在selenium定位元素操作中,如果有些元素定位不到,或者页面元素的属性有需要修改,可以通过js操作来对html页面元素获取、元素属性获取、元素的属性进行修改 selenium当中执行js代码有两种方式: 1、driver.execute_script(js代码(语句用;隔开),传入js代码当中的值) 2、使用s

    2024年02月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包