leave island

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

上面4个小节就是基本UI自动化框架了

后续小节围绕框架做细节分析

UI自动化最重要的一点就是定位元素,所以第一个分析的是selenium封装类,也就是上文中提到的webdriver_base.py。

元素定位方法参考 https://www.cnblogs.com/eastonliu/p/9088301.html

接下来根据selenium源码来看下定位元素实现原理

一、selenium定位元素源码

主要讲下面5种常见的定位方法

1、id定位: find_element_by_id()

2、name定位: find_element_by_name()

3、class定位:find_element_by_class_name()

4、xpath定位:find_element_by_xpath()

5、CSS定位:find_element_by_css_selector()

 

首先大家可以在点击进去看看他们调用的会是同一个方法(下图展示了id和xpath)

 

 

 

接着点击find_element方法看看具体实现(实现代码见下图)

当使用id、name、class定位时,实际上selenium只是对value做了处理,还是通过css来定位(所以实际上selenium页面元素定位分xpath和css定位两块)

 

 

 

最后看看我们封装类具体实现元素定位

(1)、封装类find_element方法是调用selenium的find_element方法,并且在调用基础上多了一些验证

lambda driver: driver.find_element(*loc).is_displayed() 页面存在一些隐藏属性,可以通过该条语句获取
WebDriverWait(self.driver, 10).until 页面隐形等待10s,10s内查找不到则抛元素查找超时异常

 

 

 

(2)、定位完后主要的操作是输入文本和点击

输入文本:封装类send_keys方法是调用selenium的send_keys方法,并且在调用基础上多了输入框文本情况和异常捕获并截图

点击:封装类click方法是调用selenium的click方法,并且在调用基础上多了异常捕获并截图

 

 

 (3)、为了方便元素定位,封装类定位元素设置统一入口loc_method方法,只需要调用loc_method,上面的元素定位方法都可以间接调用到

该方法4个参数

param eleLoc: 定位的元素路径 也就是id,xpath,css定位元素对应的路径
param action: 页面动作(输入文本,点击等等,可以自己扩展)
param method: 定位方式 目前支持CSS、XPATH、ID、NAME、CLASS(可以自己扩展),默认为CSS
param text: 如果是需要文本信息输入校验,才需要用到

 举例:

百度输入框原先        driver.find_element_by_id("kw").send_keys("懒勺")

封装类后                   loc_method("kw", "send_keys", method='id', text="懒勺")

百度点击搜索原先    driver.find_element_by_id("su").click()

封装类后                  loc_method("su", "click", method='id')

    def loc_method(self, eleLoc, action, method='CSS', text=None):
        """
        通用元素定位方法主入口
        :param eleLoc: 定位的元素路径
        :param action: 页面动作(输入文本,点击等等)
        :param method: 定位方式(css, path)提示:id、name、class属性都可以用css定位到,默认为CSS
        :param text: 如果是需要文本信息输入校验,才需要用到
        :return:
        """

        #loc放到selenium的driver.find_element方法就会自动识别元素
        if str(method).upper() == 'CSS':
            loc = (By.CSS_SELECTOR, eleLoc)
        elif str(method).upper() == 'XPATH':
            loc = (By.XPATH, eleLoc)
        elif str(method).upper() == 'ID':
            loc = (By.ID, eleLoc)
        elif str(method).upper() == 'NAME':
            loc = (By.NAME, eleLoc)
        elif str(method).upper() == 'CLASS':
            loc = (By.CLASS_NAME, eleLoc)
        else:
            loc = None

        try:
            if loc != None:
                if action == 'click':
                    self.click(loc)
                elif action == 'send_keys':
                    self.send_keys(text, loc)
                elif action == 'select_by_text':
                    self.select_by_text(text, loc)
                elif action == 'select_by_index':
                    self.select_by_index(text, loc)
                elif action == 'select_by_value':
                    self.select_by_value(text, loc)
                elif action == 'get_element_text':
                    return self.get_element_text(loc)
                elif action == 'get_element_attribute':
                    return self.get_element_attribute(text, loc)
                elif action == 'text_in_element':
                    return self.text_in_element(text, loc)
                elif action == 'value_in_element':
                    return self.value_in_element(text, loc)
                else:
                    logger.error("action错误:请确认action值:%s" % action)
            else:
                logger.error("method错误:请确认method值:%s" % method)
        except Exception as e:
            logger.error(e)

 

二、封装类初始化方法:

1、判断获取是否已经打开浏览器驱动,已经存在则不在创建新浏览器驱动,防止打开多个浏览器界面

2、获取驱动目前只写了谷歌,可在else里面扩展火狐,IE

    def __init__(self):
        global driver
        # 如果driver不为空,直接使用原来的driver
        if driver !=  None:
            self.driver = driver
            return

        # 获取驱动
        chromeDriverPath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'driver',
                                             'chromedriver.exe')
        option = webdriver.ChromeOptions()
        option.add_argument("disable-infobars")
        # 获取配置文件
        sysConfig = YamlUtil('sysconfig.yaml').read_yaml()
        # 找浏览器的名字
        browserName = sysConfig['browser']['browserName']
        if str(browserName).lower() == 'chrome':
            # 获取谷歌的驱动
            driver = webdriver.Chrome(executable_path=chromeDriverPath, chrome_options=option)
            self.driver = driver
        else:
            logger.error("暂不支持谷歌以外的驱动")
            raise Exception("暂不支持谷歌以外的驱动")

        if self.driver == None:
            logger.error("打开浏览器驱动失败")
            raise Exception("打开浏览器驱动失败")

        self.maximize_window()

三、封装类其他页面操作方法

主要列几个常用的(其他方法也都以注释)

1、下拉框操作     select_by_index、select_by_value

2、切换窗口      switch_to_next_window、switch_to_next_frame

3、执行js脚本    execute_script

4、退出浏览器    quit_browser

    def select_by_index(self, index, *loc):
        # 通过index 下标取select
        ele = self.find_element(*loc)
        Select(ele).select_by_index(index)
        sleep(1)

    def select_by_value(self, value, *loc):
        # 通过value值取select
        ele = self.find_element(*loc)
        Select(ele).select_by_value(value)
        sleep(1)

    def switch_to_next_window(self, currentHandle):
        # 当打开的窗口不是当前窗口,就切换
        allHandles = self.driver.window_handles
        for handle in allHandles:
            if handle != currentHandle:
                self.driver.switch_to.window(handle)
                break

    def switch_to_next_frame(self, iframe):
        # 表单切换到iframe,其中iframe是id
        self.driver.switch_to.frame(iframe)

    def execute_script(self, js):
        #执行js命令
        self.driver.execute_script(js)
        
    def quit_browser(self):
        # 退出浏览器,关闭所有窗口
        self.driver.quit()
posted on 2020-12-17 13:57  恒-星  阅读(1191)  评论(0编辑  收藏  举报