你的位置:首页 > Java教程

[Java教程]Selenium WebDriver的使用(二)


WebDriver的get()方法只会在当前窗口( current browser window)加载页面,并且会阻塞程序的运行,直至页面加载完毕(onload)或者超时,超时可以通过在初始化实例时进行设置:

1 webDriver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);//设置为10秒的超时

如果需要用一个WebDriver实例同时操作多个浏览器窗口,需要留意该特性造成的影响。默认一个WebDriver实例只会打开一个浏览器窗口,但可以使用中转页面或通过javascript:伪协议,popup出多个浏览器窗口。

对于并发测试需求,由于get的阻塞和javascript单线程执行特性,应该采用多线程来实现。

于get()方式类似的还有WebDriver.Navigation接口的to()方法,WebDriver.Navigation还有back()、forward()、refresh()方法来实现浏览器的历史导航(back()、forward()实现的是单步历史导航,不接收步长参数)

Selenium WebDriver也可以通过Selenium Standalone Server实现跨服务器的浏览器调用,具体实现参考官方文档。

WebDriver.Timeouts接口还有另外两个方法,setScriptTimeout()和implicitlyWait():

使用setScriptTimeout()方式可以设置等待一个异步脚本在抛出错误之前执行的时长。

使用implicitlyWait()方式可以设置查找元素时在抛出NoSuchElementException错误之前的等待时长,这是一个隐性的或称为全局的设置。与之对应的是Explicit Waits,具体可参考http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-and-implicit-waits。

Timeout值的设置需要根据实际需求合理设置并调优,设置了过短,在程序运行过程中将会抛出大量超时错误,过长又会降低程序效率。

另外Timeout不恰当的设置,将会在程序运行过程中,产生不可预期的等待效果,比如同时设置了显性和隐性超时时长,那么查找元素的超时时长将不确定。

 

当页面中含有frame,如果需要查找frame内部的元素,需要先使用webDriver.switchTo().frame();切换到iframe内部,再进行查找操作。

1 webDriver.switchTo().frame(0);//switch to a frame by index

frame()有三个重载形式,可传入frame的索引编号、frameElement、和name/handle字符串。如果需要切出,可以使用

1 webDriver.switchTo().defaultContent();

1 webDriver.switchTo().parentFrame();

两者的区别在于defaultContent()会切换到第一个frame或者是顶层页面;parentFrame()会切换到父一级的frame。

那么遍历iframe包括嵌套的iframe,可通过递归实现,如:

1 public static void getFrame(){2     //do something3     iLen = webDriver.findElements(By.cssSelector("body iframe")).size(); 4     for (i=0;i<iLen;i++) {5       webDriver.switchTo().frame(i);6       getFrame();7       webDriver.switchTo().parentFrame();8     };9 }

iframe可以嵌入自己所在的页面吗?答案是可以的,但不会无限制嵌入下去,只会嵌入3层,之后在内部第三层的frame就不会再嵌入了。

有些网站会用自动跳转的方法处理404错误,当有页面通过frame被嵌入到跳转目标页,如果该页面不存在,就产生了页面嵌套自身的情况,在使用Selenium WebDriver对这类iframe内容查找时,如果遍历frame的策略不当,会产生frame遍历的死循环或者导致程序抛出NoSuchFrameException异常。

2.21版本chromedriver,使用webDriver.getCurrentUrl()获取页面的url时,跟旧版本不同,在switchTo()到一个frame后,不会返回该frame的url,永远只会返回顶层页面的url。通过获取frame的src属性来识别frame页面也不是100%可靠,因为frame的页面内容是可以动态写入的。

如果需要在遍历frame的时候控制递归遍历深度,可以设置一个深度阀值,在递归过程中当达到该阀值时返回,如:

 1 static int fDepth = 2; 2 public static void getFrame() { 3   //do something 4   if (fDepth>0) { 5     iLen = webDriver.findElements(By.cssSelector("body iframe")).size();  6     for (int i=0;i<iLen;i++) { 7       fDepth--; 8       webDriver.switchTo().frame(i); 9       getFrame();10       fDepth++;11       webDriver.switchTo().parentFrame();12     };13   };14 };

Selenium WebDriver在实际使用过程中,执行速度很慢,怎么办?

待续!

原创文章,转载请标明出处。