1.简介
经过宏哥长时间的查找,终于找到了一个含有iframe的网页。所以今天这一篇的主要内容就是用这个网页的iframe,宏哥给小伙伴或者童鞋们演示一下,在处理过程中遇到的问题以及宏哥是如何解决的。
2.iframe是什么
iframe就是我们常用的iframe标签:<iframe>。iframe标签是框架的一种形式,也比较常用到,iframe一般用来包含别的页面,例如我们可以在我们自己的网站页面加载别人网站或者本站其他页面的内容。iframe标签的最大作用就是让页面变得美观。iframe标签的用法有很多,主要区别在于对iframe标签定义的形式不同,例如定义iframe的长宽高。简单的一句话概括就是:iframe 就是HTML 中,用于网页嵌套网页的。 一个网页可以嵌套到另一个网页中,可以嵌套很多层。和俄罗斯套娃差不多吧。
3.selenium处理iframe的方法
selenium提供了switch_to.frame(reference)方法来切换frame。reference是传入的参数,用来定位frame,可以传入id、name、index以及selenium的WebElement对象。
// 进入 id 叫frameA 的 iframe dr.switchTo().frame("frameA"); // 回到主窗口 dr.switchTo().defaultContent();
4.项目实战
网上找了半天也没有找到这样的例子,以前12306的日历是这种。最近升级了,已经不是这种了。完了就没有找了,偶然发现QQ邮箱的登录还是iframe这种方式的,所以宏哥就利用这个网页给大家实战演示一下。
4.1被测网址
1.被测网址的地址:https://mail.qq.com/
2.网页如下图(F12可以看到iframe标签):
3.假设宏哥想要在qq邮箱输入框输入内容,输入框的html代码如下:
4.此时宏哥在QQ邮箱输入框输入内容的代码如下:
package lessons; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; /** * @author 北京-宏哥 * *《手把手教你》系列技巧篇(四十一)-java+ selenium自动化测试 - 处理iframe-下篇(详解教程) * * 2021年11月9日 */ public class TestQQMail { public static void main(String[] args) throws InterruptedException { System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://mail.qq.com/"); Thread.sleep(5000); //By id 定位 WebElement QQMailName = driver.findElement(By.id( "u" )); QQMailName.sendKeys("test@qq.com"); } }
5.但是运行代码 后报错,如下图所示:
Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"id","selector":"u"}
6.此时小伙伴或者童鞋们是不是比较郁闷?这个输入框明显是有id属性的啊,并且属性值确实是u啊。。。那么问题在哪呢?其实就是iframe的原因,我们再仔细分析下html代码会发现沿着定位元素让上找会找到罪魁祸首iframe。如下图所示:
7.换句话说也就是我们要定位的元素时在这个 iframe中的,所以需要先切到iframe里边后才可操作。好了原因知道了,按照上一篇宏哥讲解的知识点,很轻松就可以定位到解决问题。
4.2代码设计
1.如果我们要切入的iframe有id或者name属性的话,我们可以直接通过driver.switch_to.frame并且传入要切换的iframe对应的id或者name对应属性值就可以切换到iframe,切换完后便可对我们要操作的元素进行操作。
2.如果要定位的iframe没有id或者那么的话,此时可以通过xpath、css等其他方式定位到iframe然后再进行切入。
3.使用index来区分iframe,index从0开始的。宏哥一直以为只有一个iframe,因此开始代码里写的是0结果是死活定位不到元素,后来查了一遍HTML发现是两个iframe,改成1后,立马定位元素成功!
4.3参考代码
1.传id参数
package lessons; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; /** * @author 北京-宏哥 * *《手把手教你》系列技巧篇(四十一)-java+ selenium自动化测试 - 处理iframe-下篇(详解教程) * * 2021年11月9日 */ public class TestQQMail { public static void main(String[] args) throws InterruptedException { System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://mail.qq.com/"); Thread.sleep(2000); //WebElement frame = driver.findElement(By.tagName("iframe")); driver.switchTo().frame("login_frame"); //By id 定位 driver.findElement(By.id( "switcher_plogin" )).click(); Thread.sleep(1000); WebElement QQMailName = driver.findElement(By.id( "u" )); QQMailName.sendKeys("test@qq.com"); System.out.println(" 嘿嘿!宏哥,你已经成功定位iframe内的元素啦!"); } }
2.传selenium的WebElement对象
package lessons; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; /** * @author 北京-宏哥 * *《手把手教你》系列技巧篇(四十一)-java+ selenium自动化测试 - 处理iframe-下篇(详解教程) * * 2021年11月9日 */ public class TestQQMail { public static void main(String[] args) throws InterruptedException { System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://mail.qq.com/"); Thread.sleep(2000); WebElement frame = driver.findElement(By.cssSelector("#qqLoginCard>iframe")); driver.switchTo().frame(frame); //By id 定位 driver.findElement(By.id( "switcher_plogin" )).click(); Thread.sleep(1000); WebElement QQMailName = driver.findElement(By.id( "u" )); QQMailName.sendKeys("test@qq.com"); System.out.println(" 嘿嘿!宏哥,你已经成功定位iframe内的元素啦!"); } }
3.传index参数
package lessons; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; /** * @author 北京-宏哥 * *《手把手教你》系列技巧篇(四十一)-java+ selenium自动化测试 - 处理iframe-下篇(详解教程) * * 2021年11月9日 */ public class TestQQMail { public static void main(String[] args) throws InterruptedException { System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://mail.qq.com/"); Thread.sleep(2000); //WebElement frame = driver.findElement(By.tagName("iframe")); driver.switchTo().frame(1); //By id 定位 driver.findElement(By.id( "switcher_plogin" )).click(); Thread.sleep(1000); WebElement QQMailName = driver.findElement(By.id( "u" )); QQMailName.sendKeys("test@qq.com"); System.out.println(" 嘿嘿!宏哥,你已经成功定位iframe内的元素啦!"); } }
4.4运行代码
1.运行代码,右键Run AS->Java Appliance,控制台输出,如下图所示:
2.运行代码后电脑端的浏览器的动作,如下小视频所示:
5.小结
1.在Web UI自动化的测试中,如果一个元素定位不到,那么最大的可能定位的元素属性是在 iframe 框架中,iframe 是 html 中的框架,在 html 中,所谓框架就是可以在同一个浏览器窗口中显示不止一个页面,对不同页面进行嵌套。顺着定位元素往上找,查看是否有<iframe>标签,找到说明要定位此元素,需先切换到此表单,在定位元素。
2.frame标签有frameset、frame、iframe三种,frameset跟其他普通标签没有区别,不会影响到正常的定位,而frame与iframe对selenium定位而言是一样的,selenium有一组方法对frame进行操作。
3.通常采用id和name就能够解决绝大多数问题。但有时候frame并无这两项属性,则可以用index和WebElement来定位:
index从0开始,传入整型参数即判定为用index定位,传入str参数则判定为用id/name定位
WebElement对象,即用find_element系列方法所取得的对象,我们可以用tag_name、xpath等来定位frame对象
4.如果你的电脑登录QQ后,要注意将这一行代码注释去掉,如果没有登录QQ,需要将这一行代码注释掉。因为QQ已经登录,然后登录邮箱默认快捷登录,就会看不到账号密码登录的元素,出现找不到元素的报错。
//driver.findElement(By.id( "switcher_plogin" )).click();//定位帐号密码登录并点击