赞
踩
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']
可以看到,打印出来两个窗口,第一个f75e8ddc-5367-47e2-b458-1a7681ce9e13是百度搜索窗口id,第二个是淘宝页面的窗口id,但是当前的句柄是在百度搜索页面窗口,也就是说,如果要在淘宝页面进行元素定位,需要先将窗口句柄切换到淘宝页面,才能进行元素定位。
那么如何切换窗口呢?
Python的WebDriver模块提供了switch_to方法,源码如下。注释部分已经为我们提供了几种切换用法,有切换iframe,切换窗口,退回主页面…
方法 | 作用 |
---|---|
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
我们用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()
♡ \color{red}{\heartsuit} ♡
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()
可以用显式等待,等待直到iframe切换成功。在代码中加入这些即可,不知道显式等待的,可以看下我的上篇介绍。
# 等待iframe切换成功
wait = WebDriverWait(self.driver, 3)
wait.until(expected_conditions.frame_to_be_available_and_switch_to_it(iframe))
♡ \color{red}{\heartsuit} ♡
alter弹窗的切换也是类似的,只是把上面的代码改吧改吧,wait.until(expected_conditions.alert_is_present())
目前alter弹窗用的也相对少了,我找不到网站来演示。暂时不介绍了。之后有相关的,再补充。
哈哈哈,终于让我找到了别人写的弹窗:web自动化测试-文件上传与弹框处理
以下摘抄了一些这位网页写的
在页面操作中有时会遇到 JavaScript 所生成的 alert、confirm 以及 prompt 弹框,可以使用 switch_to.alert () 方法定位到。然后使用 text、accept、dismiss、send_keys 等方法进行操作。
输入一段文本点击比如提交按钮,会弹出确认内容的弹框,这种场景可以使用下面的方式处理:
通过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()
下节分享6-UI自动化-鼠标键盘操作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。