看到这篇文章就算赚到!里面就有解决整天切换 iframe 的方法。
我们公司已经开发了 3 年的 WEB UI 自动化测试框架,但是 iframe 的切换至今是痛点,遇见 iframe 得一层层切换,早在去年本人就提出有没办法去掉 iframe 切换,脚本直接写各种 xpath 即可。
所以本文的重点(因为有同学不晓得本文重点是什么)是如何在自动化测试脚本中,不再出现 driver.switchTo().frame(i);、driver.switchTo().defaultContent();、driver.switchTo().parentFrame() 这些语句,因为如果要切换框架,写脚本的同学得对着 iframe 一个个去数或者写 iframe 的 xpath,还得切换做切换回默认框架,父框架等脚本,非常不方便!如果在日常工作中,你不知道 iframe 是什么,也没有碰到 iframe 那就不需要看这篇文章了
首先我们公司的框架是使用 JAVA 的,解决 iframe 切换的关键是能够通过 xpath 获取界面上的所有元素,选择每个界面上的元素。所以我们需要用到一个第三方包 JsoupXpath 以及一系列相关的关联包,需要的同学可以百度下载,或加我的微信 423462664 领取。
有了包,我们还需要理解 iframe 在 selenium 到底是什么样的。我们可以通过 driver.getPageSource();方法获取 selenium 能够看到的网页代码,当我们对着有 iframe 的页面拉取时,我们会发现,iframe 里的东西都是空的!!
当切换了 iframe 之后,在调用 driver.getPageSource();方法,界面的代码就变成了:
我们看到上面的代码 iframe 的标签不见了,取而代之的是整个页面只出现 iframe 底下的代码,除了 #document 标记,请看下图,下图是在 chrome 里看到的 iframe 底下代码。
所以我们想利用文档一次性拿下包括 iframe 的源码是不可能的,本人一开始想到的解决方案是通过 driver.getPageSource();拿到所有包括 iframe 底下源码,再找到需要点击的元素,再逐级向上级寻找,生成相对应 xpath,通过传入 xpath 和 driver 对象进行操作,因为不能够知道主 html 下的 iframe 里的代码,也不知道 iframe 下的 iframe 有无更多的 iframe,要解决这里就必须使用递归,去寻找各个 iframe 里是否有匹配的代码,而 JsoupXpath 里提供了所需要的全部接口。下面是代码:
/**
* 在各个iframe中寻找元素
* 作者:李星明
* 2018-10-17
* @author Xingming.Li
* @param driver webdriver对象,注意传递过来时,清除至默认框架,意思是调用
* @param xpath 需要寻找元素的xpath,该方法仅支持使用xpath时的搜索
* @return 返回
*/
public static WebElement findIframeElement(WebDriver driver ,String xpath)
{
String pageSource = driver.getPageSource();
WebElement element = null;
try{
element = driver.findElement(By.xpath(xpath));
}catch(Exception e)
{
e.printStackTrace();
}
if(null!= element)
{
return element;
}
boolean ifHasIframe = jsoupUtil.ifHasIframe(pageSource);
if(ifHasIframe == true)
{
int i = 0;
while(true)
{
try{
driver.switchTo().frame(i);
element = findIframeElement(driver,xpath);
if(null!= element)
{
return element;
}
//返回父框架寻找下一个
driver.switchTo().parentFrame();
}catch(Exception e)
{
e.printStackTrace();
break;
}
i++;
}
}else
{
}
return null;
}
public static boolean ifHasIframe(String pageSource)
{
String xpath="//iframe";
JXDocument jxDocument = new JXDocument(pageSource);
List<Object> rs = jxDocument.sel(xpath);
for (Object o:rs){
if (o instanceof Element){
// int index = ((Element) o).siblingIndex();
// System.out.println(index);
// Element element = (Element) o;
return true;
}
System.out.println(o.toString());
}
return false;
}
通过调用 findIframeElement(WebDriver driver ,String xpath),能够有效找出 html 与所有 iframe 底下匹配的 xpath(注意,匹配的 xpath 必须是唯一)
在实际调用中,可能很多同学已经切换了多个 iframe,findIframeElement 这个方法是在出现了异常之后,进行调用的,调用之前之后都需要做一定的处理,下面是我在点击行为时,调用的代码
//打印异常
e.printStackTrace();
driver.switchTo().defaultContent();
element = jsoupUtil.findIframeElement(driver, rePath);
if(null!= element)
{
System.out.println("查找成功");
try{
element.click();
}catch(Exception e2)
{
}
//如果下一个行为不需要切换框架即可点击,则不要先切回到最主要的框架里去。
// driver.switchTo().defaultContent();
}else
{
System.out.println("查找失败");
if (null != Parameter.getParameter("uploadExption")
&& Parameter.getParameter("uploadExption")
.equals("1"))
{
new exceptionAction().reportExption(...);
}
return failed(...);
}
}
我们在实际的项目使用中很快就遇到了在 chrome 浏览器复制 xpath,但是在搜索中能够匹配两次 xpath 的控件,必须要通过修改 xpath 使得该控件唯一,才能使得脚本能够正常运行。(下面提供一个实际案例)
如红圈所示,提交与发送按钮在 chrome 浏览器复制 xpath 时居然是一样的!
必须修改成唯一方能放至程序执行。譬如改成如下的:
//*[@id="btnSubmit"][@value="提 交"]
我们遇到问题,首先是要想到能够解决,然后再是有能力去解决,但我却还没看到有人能够贡献出来代码真正解决这些问题,希望各位大神多多加油多多共享自己 的代码。