• 5-UI自动化-三大切换,iframe如何定位,窗口新开、alert弹窗如何进行元素定位


    5-UI自动化-三大切换,iframe如何定位,窗口新开、alert弹窗如何进行元素定位

    上篇介绍4-UI自动化-selenium三大等待操作

    web测试过程中有没有遇到以下问题:
    1、测试过程中遇到点击后打开了一个新的窗口,这种要如何定位呢?
    2、页面嵌套iframe,如何定位元素?
    3、有些甚至有alert弹窗,(基本较少,一些银行网站可能会有),如何定位元素?

    本篇就来一一介绍

    ♡ \color{red}{\heartsuit}

    新开一个窗口如何定位元素

    比如我输入百度url,输入淘宝,点击打开淘宝,然后在淘宝搜索连衣裙,点击淘宝会新开一个窗口,那么这个如何定位呢?

    先要了解下窗口句柄的概念。窗口句柄其实可以理解为是窗口的id。
    Python的WebDriver模块中,提供了相关方法。
    这里截取了current_window_handle()和window_handles()源码,从方法名其实就可以看出,current_window_handle是当前窗口句柄,返回的是一个str类型,window_handles()是返回当前会话的所有窗口,是一个列表。

     	@property
        def current_window_handle(self) -> str:
            """
            Returns the handle of the current window.
    
            :Usage:
                ::
    
                    driver.current_window_handle
            """
            return self.execute(Command.W3C_GET_CURRENT_WINDOW_HANDLE)['value']
    
        @property
        def window_handles(self) -> List[str]:
            """
            Returns the handles of all windows within the current session.
    
            :Usage:
                ::
    
                    driver.window_handles
            """
            return self.execute(Command.W3C_GET_WINDOW_HANDLES)['value']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    可以看到,打印出来两个窗口,第一个f75e8ddc-5367-47e2-b458-1a7681ce9e13是百度搜索窗口id,第二个是淘宝页面的窗口id,但是当前的句柄是在百度搜索页面窗口,也就是说,如果要在淘宝页面进行元素定位,需要先将窗口句柄切换到淘宝页面,才能进行元素定位。

    在这里插入图片描述
    那么如何切换窗口呢?

    Python的WebDriver模块提供了switch_to方法,源码如下。注释部分已经为我们提供了几种切换用法,有切换iframe,切换窗口,退回主页面…

    switch_to方法

    方法作用
    alert = driver.switch_to.alert切换alter弹窗
    driver.switch_to.default_content()退回主页面
    driver.switch_to.frame(‘frame_name’)通过窗口名切换窗口
    driver.switch_to.frame(0)通过索引切换窗口
    driver.switch_to.parent_frame()退回父级iframe
     	@property
        def switch_to(self) -> SwitchTo:
            """
            :Returns:
                - SwitchTo: an object containing all options to switch focus into
    
            :Usage:
                ::
    
                    element = driver.switch_to.active_element
                    alert = driver.switch_to.alert
                    driver.switch_to.default_content()
                    driver.switch_to.frame('frame_name')
                    driver.switch_to.frame(1)
                    driver.switch_to.frame(driver.find_elements_by_tag_name("iframe")[0])
                    driver.switch_to.parent_frame()
                    driver.switch_to.window('main')
            """
            return self._switch_to
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    我们用switch_to.window()就可以解决我们的问题,需要将窗口id传进去,但是print(self.driver.current_window_handle) handles = self.driver.window_handles获取到的分别是当前窗口(百度页面),和所有窗口,所有窗口列表中第二个是我们想要元素定位的窗口,那么要怎么传进第二个窗口名呢?不要忘了,它是一个列表,通过列表的取值就可以获取,-1表示获取最后一个窗口,也就是我们新开的窗口。self.driver.switch_to.window(handles[-1])切换到新窗口。

    在这里插入图片描述

    可以看到成功切换窗口了,那么接下来就回到老知识了,用之前学习过的元素定位就可以了

    在这里插入图片描述

    最终代码

    import time
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    
    
    class SwitchSample:
    
        def __init__(self):
            self.driver = webdriver.Firefox()
            # 在打开浏览器驱动等待3s,再去输入url
            self.driver.implicitly_wait(3)
            self.driver.get('http://baidu.com')
    
        def switch_window(self):
            self.driver.find_element(By.ID, 'kw').send_keys('淘宝')
            # 在点击百度一下前先等待2s
            self.driver.find_element(By.ID, 'su').click()
            # 在输出浏览器的标题前,先等待3s,防止浏览器还未加载完全
            time.sleep(3)
            # 点击淘宝
            self.driver.find_element(By.LINK_TEXT, '淘宝').click()
            print(self.driver.title)
            print("当前的窗口{}".format(self.driver.current_window_handle))
            handles = self.driver.window_handles
            print("当前所有窗口{}".format(handles))
            self.driver.switch_to.window(handles[-1])
            print(f"切换后新的窗口{self.driver.current_window_handle}")
            time.sleep(2)
            self.driver.find_element(By.ID, 'q').send_keys('连衣裙')
            print(self.driver.current_url, self.driver.title)
            time.sleep(2)
            self.driver.close()
            self.driver.quit()
    
    
    if __name__ == '__main__':
        ss = SwitchSample()
        ss.switch_window()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述

    ♡ \color{red}{\heartsuit}

    iframe定位元素

    IFRAME是HTML标签,作用是文档中的文档,或者浮动的框架(FRAME)。iframe元素会创建包含另外一个文档的内联框架(即行内框架)。

    如果你用Selenium定位的目标元素在某个iframe里,需要先执行switch_to_frame,否则会找不到元素。

    标签是一个内联框架,即用来在当前 HTML 页面中嵌入另一个文档的,且所有主流浏览器都支持iframe标签。

    如网易云音乐网站,https://music.163.com/,点击进入网页,F12,查看网页elements,然后点击用户登录。用户登录的id属性为"index-enter-default"。

    如果直接通过定位元素driver.find_element(By.ID, "index-enter-default").click(),会出现报错:selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: [id="index-enter-default"]

    因为用户登录是在iframe中的
    在这里插入图片描述
    如果想找一个 iframe 当中的元素,不能直接查找,而是先要进入iframe当中。
    我们先要定位iframe元素,进入iframe中,然后再去定位iframe当中的元素。代码实现如下:

    import time
    
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    
    class SwitchIframe:
    
        def __init__(self):
            self.driver = webdriver.Firefox()
            self.driver.maximize_window()
            # 在打开浏览器驱动等待3s,再去输入url
            self.driver.implicitly_wait(3)
            self.driver.get('https://music.163.com/')
    
        def switch_iframe(self):
            # 先定位iframe元素,然后切换进入iframe
            iframe = self.driver.find_element(By.ID, "g_iframe")
            # 等待iframe切换成功
            wait = WebDriverWait(self.driver, 3)
            wait.until(expected_conditions.frame_to_be_available_and_switch_to_it(iframe))
            # 加入显式等待,让代码更智能,增强代码的健壮性
            # self.driver.switch_to.frame(iframe)
            # 找到用户登录,点击
            self.driver.find_element(By.ID, "index-enter-default").click()
            print(self.driver.title)
            time.sleep(2)
            self.driver.close()
            self.driver.quit()
    
    
    if __name__ == '__main__':
        si = SwitchIframe()
        si.switch_iframe()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述
    可以用显式等待,等待直到iframe切换成功。在代码中加入这些即可,不知道显式等待的,可以看下我的上篇介绍。

    # 等待iframe切换成功
    wait = WebDriverWait(self.driver, 3)
    wait.until(expected_conditions.frame_to_be_available_and_switch_to_it(iframe))
    
    • 1
    • 2
    • 3

    ♡ \color{red}{\heartsuit}

    alert弹窗如何定位元素

    alter弹窗的切换也是类似的,只是把上面的代码改吧改吧,wait.until(expected_conditions.alert_is_present())目前alter弹窗用的也相对少了,我找不到网站来演示。暂时不介绍了。之后有相关的,再补充。

    哈哈哈,终于让我找到了别人写的弹窗:web自动化测试-文件上传与弹框处理

    以下摘抄了一些这位网页写的

    在页面操作中有时会遇到 JavaScript 所生成的 alert、confirm 以及 prompt 弹框,可以使用 switch_to.alert () 方法定位到。然后使用 text、accept、dismiss、send_keys 等方法进行操作。

    • text:返回 alert、confirm、prompt 中的文字信息。
    • accept ():接受现有警告框,即点击确定。
    • dismiss ():解散现有警告框,即点击取消。
      send_keys (keysToSend):发送文本至警告框。keysToSend: 将文本发送至警告框。

    输入一段文本点击比如提交按钮,会弹出确认内容的弹框,这种场景可以使用下面的方式处理:

    在这里插入图片描述
    通过name属性定位元素
    在这里插入图片描述
    同理,如果想要自定义输出弹窗内容,定位输入的元素,输入自定义内容即可。
    在这里插入图片描述

    import time
    
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.support.wait import WebDriverWait
    
    
    class AlertDemo:
        def __init__(self):
            self.driver = webdriver.Firefox()
            self.driver.maximize_window()
            self.driver.implicitly_wait(3)
    
        def switch_alert(self):
            """Alert弹窗获取文本与确认操作"""
            self.driver.get("http://sahitest.com/demo/alertTest.htm")
            time.sleep(3)
            # 可以自定义弹窗的输出内容
            wait = WebDriverWait(self.driver, 5, 0.5)
            locator = ('xpath', '//input[@name="t1"]')
            wait.until(expected_conditions.visibility_of_element_located(locator)).send_keys('金聪聪,冲冲冲')
            # self.driver.find_element('xpath', '//h2').send_keys("金聪聪,冲冲冲!")
            self.driver.find_element(By.NAME, "b1").click()
            # 添加显示等待,等待弹框的出现
            WebDriverWait(self.driver, 5, 0.5).until(expected_conditions.alert_is_present())
            # 切换到弹框
            alert = self.driver.switch_to.alert
            # 打印弹框的文本
            print(alert.text)
            time.sleep(3)
            # 点击确定,弹窗消失
            alert.accept()
            # 点击取消或者关闭弹框
            # alert.dismiss()
    
    
    if __name__ == '__main__':
        ad = AlertDemo()
        ad.switch_alert()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    下节分享6-UI自动化-鼠标键盘操作

  • 相关阅读:
    系统学习Python——类(class)代码的编写基础与实例(一):代码的编写基础
    【学习日志】2022.11.11 合同矩阵、惯性指数、委托构造、继承控制、=delete、可变参数模板类
    python渗透测试入门——流量嗅探器
    计算机毕设(附源码)JAVA-SSM基于的校园疫情防控管理
    NumPy(二)
    LeetCode第118题—杨辉三角
    C++二分算法: 找出第 K 小的数对距离
    Github访问加速
    stm32cubemx hal学习记录:TIMER输入捕获
    【Spring Boot】034-Spring Boot 整合 JUnit
  • 原文地址:https://blog.csdn.net/weixin_41948075/article/details/128077382