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如何設置,都不會對它有任何影響。
固然,咱們通常不會將超時時間設爲負數,不然無任何意義,這裏只是想驗證一下官方的說法而已,結果說明與官方文檔的說法稍有些出入。因此,若是想使設置異步腳本超時的這句代碼無效,最好的方法仍是將它註釋掉,而非將超時時間改爲負數。