Selenium可以执行js,这使得Selenium拥有更为强大的能力。既然能执行js,那么js能作的事,Selenium应该大部分也能作。这应该得益于JavascriptExecutor这个接口,而ChromeDriver, EdgeDriver, EventFiringWebDriver, FirefoxDriver, InternetExplorerDriver, OperaDriver, RemoteWebDriver, SafariDriver均实现了这个接口。跟使用WebDriver同样,咱们能够这样使用该接口: html
WebDriver driver=new ChromeDriver(); JavascriptExecutor jsExecutor=(JavascriptExecutor) driver;
该接口十分简单,只有两个方法:java
1.java.lang.Object executeScript(java.lang.String script, java.lang.Object... args) 同步执行jsgit
2.java.lang.Object executeAsyncScript(java.lang.String script, java.lang.Object... args) 异步执行jsgithub
对于返回值:web
1.若是js返回的是html元素,那么方法返回WebElementchrome
2.若是js返回的是小数,方法返回Doubleapi
3.若是js返回的是非小数,方法返回Long数组
4.若是js返回的是布尔,方法返回Boolean异步
5.若是js返回的是其余,方法返回Stringasync
6.若是js返回的是数组,方法返回List<Object>,能够嵌套,Object的值的类型是根据上面5条而定。
7.若是js返回的是map,方法返回Map<String, Object>,Object值类型的定义同上。
8.若是js返回null或没有返回,方法返回null
对于 arg参数:
js会用一个“魔法”变量arguments来接收。参数的类型能够是:数字,布尔,字符串,元素(WebElement)以及List<Object>,Object类型为上述类型
下面经过一些简单的例子,来讲明用法
首先,咱们在项目的html文件夹增长一个空白的html文件,jsTest.html
html的代码以下:这是一个空白的html
<html> <head> </head> <body> </body> </html>
咱们的代码:
System.setProperty("webdriver.chrome.driver", "D:/WorkSpace/SeleniumTest/tools/chromedriver.exe"); WebDriver driver=new ChromeDriver(); driver.get("file:///D:/WorkSpace/SeleniumTest/html/jsTest.html"); //调用js,弹出信息 ((JavascriptExecutor) driver).executeScript("alert('hello,selenium');");
执行的效果以下:
是否是很是简单,咱们尝试使用带有参数的调用:
System.setProperty("webdriver.chrome.driver", "D:/WorkSpace/SeleniumTest/tools/chromedriver.exe"); WebDriver driver=new ChromeDriver(); driver.get("file:///D:/WorkSpace/SeleniumTest/html/jsTest.html"); //调用js,"11111","22222"等参数将会被arguments接收,成为一个数组,此处arguments[0]表示调用第一个参数 ((JavascriptExecutor) driver).executeScript("alert(arguments[0]);","1111111","222222");
执行的效果:
咱们再修改一下jsTest.html,增长一个js方法,代码以下:
<html> <head> <script> function sayHello() { alert("hi,Selenium"); } </script> </head> <body> </body> </html>
调用的java改为以下:
System.setProperty("webdriver.chrome.driver", "D:/WorkSpace/SeleniumTest/tools/chromedriver.exe"); WebDriver driver=new ChromeDriver(); driver.get("file:///D:/WorkSpace/SeleniumTest/html/jsTest.html"); //调用页面上的方法 ((JavascriptExecutor) driver).executeScript("sayHello()");
发现依然能够执行成功,效果以下:
对于异步执行,使用的方法是相似的。更详细的可参考官网:http://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
可是对于异步执行,Selenium提供了一个时间限制的方法:
WebDriver.Timeouts setScriptTimeout(long time, java.util.concurrent.TimeUnit unit)
该方法是针对 executeAsyncScript 方法的执行,对executeScript无效。官方的文档说: If the timeout is negative, then the script will be allowed to run indefinitely.若是timeout的时间设为负数,表示不限执行时间,但我发现,设置为负数,同样会抛出异常(固然,官方没有说不会抛出异常,但抛出异常后,后面的代码就没法执行,除非本身去捕捉这个异常进行额外的处理)。
System.setProperty("webdriver.chrome.driver", "D:/WorkSpace/SeleniumTest/tools/chromedriver.exe"); WebDriver driver=new ChromeDriver(); driver.get("file:///D:/WorkSpace/SeleniumTest/html/jsTest.html"); //设置超时时间为-1秒 driver.manage().timeouts().setScriptTimeout(-1, TimeUnit.SECONDS); JavascriptExecutor js=(JavascriptExecutor) driver; //3秒后执行 js.executeAsyncScript("setTimeout(\"alert('本信息3秒后弹出!')\",3000)");
3秒后,js依然能弹出框,但以前就已经先抛出异常。也就是说,超时并未中止js的执行,只是抛出异常。
异常信息为:Exception in thread "main" org.openqa.selenium.ScriptTimeoutException:asynchronous script timeout: result was not received in -1 seconds
若是将超时时间设置为3或以上,则js能顺利执行,而且不会抛出异常。
若是是executeScript,则不管setScriptTimeout如何设置,都不会对它有任何影响。
固然,咱们通常不会将超时时间设为负数,不然无任何意义,这里只是想验证一下官方的说法而已,结果说明与官方文档的说法稍有些出入。因此,若是想使设置异步脚本超时的这句代码无效,最好的方法仍是将它注释掉,而非将超时时间改为负数。