1113Selenium web自动化测试经验分享-frame切换时的定位、expected_conditions模块的frame_to_be_available_and_switch_to_it()

这篇分享里面坑很多,不推荐掌握;我是爬了又掉,接着爬,接着掉坑,到现在总算是有点收获。

一)frame表单切换时的定位方法

大家都知道,对于不同的iframe/frame表单中的元素是无法直接定位的。需要先结合switchTo().frame()方法切换到指定的frame/iframe中。

关于定位方法,个人建议 2点:driver.switch_to.frame(xxxx) xxxx 可以是id属性值;或是查找到这个元素(WebElement)。

可能很多人会说 name属性也是可以用的,但为了方便记忆后面的frame_to_be_available_and_switch_to_it()的用法,就比较推荐那id和WebElement来定位。

关于邮箱登录时iframe的切换,有些网站(126邮箱、Yeah.net网易免费邮)和163的是类似,动态id;有些网站是没有设置iframe,可以直接定位到输入框;还有些是和QQ邮箱(189邮箱、21CN个人邮箱、阿里邮箱)类似,id是固定属性值;

    def test_57o1(self):
        """expected_conditions模块下的frame_to_be_available_and_switch_to_it()"""
        # frame的定位 driver.switch_to.frame(xxxx)   xxxx 可以是id属性值;或是查找到这个元素WebElement,不可以使用locator元组

        driver = webdriver.Chrome()
        driver.maximize_window()
        driver.get('https://mail.163.com/')

        # 

        frame1 = self.xin_find_element(driver, By.CSS_SELECTOR, 'iframe[frameborder="0"]')    # 查找到这个元素WebElement,通过
        # frame1 = 'id'     # 无法尝试 动态id

        driver.switch_to.frame(frame1)
        self.xin_find_element(driver, By.CSS_SELECTOR, 'input[placeholder="邮箱帐号或手机号码"]').clear()
        self.xin_find_element(driver, By.CSS_SELECTOR, 'input[placeholder="邮箱帐号或手机号码"]').send_keys('185')

        time.sleep(1)
        driver.quit()

上图代码是处理 163邮箱登录界面iframe:动态id,推荐WebElement来定位。

    def test_57o3(self):
        """expected_conditions模块下的frame_to_be_available_and_switch_to_it()"""
        # frame的定位 driver.switch_to.frame(xxxx)   xxxx 可以是id属性值;或是查找到这个元素WebElement,不可以使用locator元组

        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)
        self.driver.get("https://mail.qq.com/")

        # 

        # frame11 = "login_frame"       # 通过 但是无法确定是id 还是name属性值来做的判断
        # frame11 = (By.XPATH, '//iframe[@frameborder="0"]')      # 报错 Message: unknown error: invalid 'id'
        frame11 = self.driver.find_element(By.XPATH, '//iframe[@frameborder="0"]')      # 查找到这个元素WebElement 通过
        self.driver.switch_to.frame(frame11)

        self.driver.find_element_by_id("switcher_plogin").click()   # 账号密码登录
        self.driver.find_element_by_id("u").clear()
        self.driver.find_element_by_id("u").send_keys('987654')

        time.sleep(1)
        self.driver.quit()

上图代码是处理 QQ邮箱登录界面的iframe:推荐id定位和WebElement。

二)expected_conditions模块下的frame_to_be_available_and_switch_to_it()

expected_conditions模块下有个类frame_to_be_available_and_switch_to_it(),主要是用来判断该frame是否可以switch进去。
单独使用:可传入定位方式id属性值,成功的话就返回True并switch进去,否则 返回False;也可传入locator元组或WebElement,成功定位的话就返回True并switch进去,否则 会报错,找不到定位。

    def test_57o4(self):
        """expected_conditions模块下的frame_to_be_available_and_switch_to_it()"""
        # frame_to_be_available_and_switch_to_it() 判断该frame是否可以switch进去
        # 如果直接传入定位方式id,可以的话就返回True并switch进去,否则返回False
        # 也可传入locator元组或WebElement,可以的话就返回True并switch进去,否则报错,找不到定位

        from selenium.webdriver.support.wait import WebDriverWait
        from selenium.webdriver.support import expected_conditions as EC
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(5)
        self.driver.get("https://mail.qq.com/")
        print('0', time.ctime())
        # 

        # 直接传入定位方式id
        # print(EC.frame_to_be_available_and_switch_to_it('login_frame')(self.driver))        # 正确的 返回True并switch进去
        # print(EC.frame_to_be_available_and_switch_to_it('login_frame123')(self.driver))     # 错误的 返回False

        # 传入locator元组
        # print(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[frameborder="0"][width="100%"]'))(self.driver))       # 正确的 返回True并switch进去
        # print(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[frameborder="10"]'))(self.driver))    # 报错 Message: no such element

        # 传入WebElement
        abcd = self.driver.find_element(By.XPATH, '//iframe[@height="100%" and @scrolling="no"]')       # 正确的 返回True并switch进去
        # abcd = self.driver.find_element(By.XPATH, '//iframe[@height="1000%" and @scrolling="no123"]')       # 报错 Message: no such element
        print(EC.frame_to_be_available_and_switch_to_it(abcd)(self.driver))

        self.driver.find_element_by_id("switcher_plogin").click()
        self.driver.find_element_by_id("u").clear()
        self.driver.find_element_by_id("u").send_keys('987654')
        self.driver.switch_to.default_content()
        print('1', time.ctime())

        time.sleep(1)
        self.driver.quit()
class frame_to_be_available_and_switch_to_it(object):
    """ An expectation for checking whether the given frame is available to
    switch to.  If the frame is available it switches the given driver to the
    specified frame.
    """
    def __init__(self, locator):
        self.frame_locator = locator

    def __call__(self, driver):
        try:
            if isinstance(self.frame_locator, tuple):
                driver.switch_to.frame(_find_element(driver,
                                                     self.frame_locator))
            else:
                driver.switch_to.frame(self.frame_locator)
            return True
        except NoSuchFrameException:
            return False

源码没怎么看懂 = =

分享下 自己琢磨出来的经验:

frame_to_be_available_and_switch_to_it()和显式等待结合后,传入定位方式id、locator元组,可以的话就返回True并switch进去,否则 超时报错 selenium.common.exceptions.TimeoutException;传入WebElement,可以的话就返回True并switch进去,否则找不到定位报错 selenium.common.exceptions.NoSuchElementException: Message: no such element。 (报错类型不同)

    def test_57o7(self):
        """expected_conditions模块下的frame_to_be_available_and_switch_to_it()"""

        # frame_to_be_available_and_switch_to_it() 判断该frame是否可以switch进去
        # 如果直接传入定位方式id,可以的话就返回True并switch进去,否则返回False
        # 也可传入locator元组或WebElement,可以的话就返回True并switch进去,否则报错,找不到定位

        # 和显式等待结合后,传入定位方式id、locator元组,可以的话就返回True并switch进去,否则 超时报错 selenium.common.exceptions.TimeoutException
        # 和显式等待结合后,传入WebElement,可以的话就返回True并switch进去,否则报 找不到定位报错 selenium.common.exceptions.NoSuchElementException: Message: no such element

        # 此外 WebElement因为是去定位某个元素,定位不到会报错,应该放在try里面,放在try前面 会执行到那一步就直接报错;
        # 定位某个元素的WebElement放在try里面,但又用不到那个显式等待的!在执行前就已经报错 找不到元素。
        # 对比 错误的locator元组(放在里面、外面都可以,因为不查找)是用的当前的显式等待!  建议都是放在try里面
        from selenium.webdriver.support.wait import WebDriverWait
        from selenium.webdriver.support import expected_conditions as EC
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(5)
        self.driver.get("https://webmail30.189.cn/w2/")  # 189邮箱
        print('start', time.ctime())

        # 

        print(EC.frame_to_be_available_and_switch_to_it('iframeLogin')(self.driver))
        self.driver.find_element(By.XPATH, '//input[@name="userName" or @id="userName"]').send_keys('987')
        self.driver.switch_to.default_content()
        print('0', time.ctime())

        time.sleep(1)  # 执行速度太快

        WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it('iframeLogin'), '失败')
        self.driver.find_element(By.XPATH, '//input[@id="userName"]').clear()
        self.driver.switch_to.default_content()
        print('00', time.ctime())

        time.sleep(1)

        print(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[class="login_iframe"]'))(self.driver))
        self.driver.find_element(By.XPATH, '//input[@name="userName" or @id="userName"]').send_keys('654')
        self.driver.switch_to.default_content()
        print('1', time.ctime())

        time.sleep(1)

        WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[class="login_iframe"]')), '失败')
        self.driver.find_element(By.XPATH, '//input[@id="userName"]').clear()
        self.driver.switch_to.default_content()
        print('10', time.ctime())

        time.sleep(1)

        ABCD = self.driver.find_element(By.ID, 'iframeLogin')
        print(EC.frame_to_be_available_and_switch_to_it(ABCD)(self.driver))
        self.driver.find_element(By.XPATH, '//input[@id="userName"]').send_keys('321')
        self.driver.switch_to.default_content()
        print('2', time.ctime())

        time.sleep(1)

        ABCD1 = self.driver.find_element(By.ID, 'iframeLogin')
        WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it(ABCD1), '失败')
        self.driver.find_element(By.XPATH, '//input[@id="userName"]').clear()
        self.driver.switch_to.default_content()
        print('20', time.ctime())

        try:
            ABCD11 = self.driver.find_element(By.ID, 'iframeLogin111111')
            WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it(ABCD11), '失败')
            self.driver.find_element(By.XPATH, '//input[@id="userName"]').clear()
            self.driver.find_element(By.XPATH, '//input[@id="userName"]').send_keys('666')
            self.driver.switch_to.default_content()
        except BaseException as e11:
            print(e11)      # Message: no such element: Unable to locate element: {"method":"id","selector":"iframeLogin111111"}
        print('3', time.ctime())    # 5秒的隐式等待

        try:
            ABCD22 = (By.CSS_SELECTOR, 'iframe11111111[class="login_iframe"]')
            WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it(ABCD22), '失败')
            self.driver.find_element(By.XPATH, '//input[@id="userName"]').clear()
            self.driver.find_element(By.XPATH, '//input[@id="userName"]').send_keys('666666')
            self.driver.switch_to.default_content()
        except BaseException as e111:
            print(e111)
        print('4', time.ctime())

        try:
            WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it('22222222'), '没能成功')
            self.driver.find_element(By.XPATH, '//input[@id="userName"]').clear()
            self.driver.find_element(By.XPATH, '//input[@id="userName"]').send_keys('6666666666')
            self.driver.switch_to.default_content()
        except BaseException as e11111:
            print(e11111)
        print('5', time.ctime())

        # WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it('22222222'), '没能成功')
        # 报错 selenium.common.exceptions.TimeoutException: Message: 没能成功

        # WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe11111111[class="login_iframe"]')), '失败')
        # 报错 selenium.common.exceptions.TimeoutException: Message: 失败

        # WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it(self.driver.find_element(By.ID, 'iframeLogin111111')), '失败')
        # 报错 selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"id","selector":"iframeLogin111111"}
        print('end', time.ctime())
        time.sleep(1)
        self.driver.quit()

实际看我用例的名称就知道写的好几个,但是因为此次分享在实际工作中不常见,所以就分享了一个。

交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie

你可能感兴趣的:(Web自动化测试)