顯式等待-----Selenium快速入門(十)
上一篇說了元素定位過程中的隱式等待,今天我們來探討一下顯示等待。顯式等待,其實就是在使用WebDriverWait這個對象,進行等待。顯式等待對比隱式等待,多了一些人性化的設置,可以說是更細化的隱式等待。
WebDriverWait 類繼承自泛型類 FluentWait<T> ,而這個泛型類,又是泛型接口 Wait<T> 的實現。Wait<T>這個泛型接口只有一個方法,就是until,這也是我們需要重點掌握的方法,而FluentWait<T>實現了until方法,而且還擴充了一些設置,例如,設置等待時間,每隔多少時間執行一次,執行過程中哪些異常可以忽略,以及超時的時候顯示的信息。同樣,WebDriverWait既然繼承了FluentWait<T>,也會擁有一樣的方法。
首先,我們如何得到WebDriverWait的實例呢,他的構造函數有3個。
1.WebDriverWait(WebDriver driver, Clock clock, Sleeper sleeper, long timeOutInSeconds, long sleepTimeOut)
driver:這個不用說,大家都應該知道。
clock:Clock是一個接口,clock參數是用來定義超時,一般使用默認即可。關於更詳細的Clock接口,可以點擊這裏
sleeper:Sleeper也是一個接口,sleeper這個參數是,讓當前線程進入睡眠的一個對象
timeOutInSeconds:超時的時間,單位是秒
sleepTimeOut:線程睡眠的時間,默認是500毫秒,也就是默認500毫秒執行一次
2.WebDriverWait(WebDriver driver, long timeOutInSeconds)
3.WebDriverWait(WebDriver driver, long timeOutInSeconds, long sleepInMillis)
有了第一個構造函數的解釋,後面兩個就很簡單了,實際上,後面兩個構造函數更常用。
由於Clcok和Sleeper都是接口,我們可以自己重新實現,也可以用已有的實現,例如,SystemClock就實現了Clock,而Sleeper,他有一個static final的字段SYSTEM_SLEEPER,我們可以使用它來作為參數。下面是Sleeper接口的源碼
public interface Sleeper { public static final Sleeper SYSTEM_SLEEPER = new Sleeper() { public void sleep(Duration duration) throws InterruptedException { Thread.sleep(duration.in(TimeUnit.MILLISECONDS)); } }; /** * Sleeps for the specified duration of time. * * @param duration How long to sleep. * @throws InterruptedException If the thread is interrupted while sleeping. */ void sleep(Duration duration) throws InterruptedException; }
所以,要使用構造函數一得到wait對象,可以這樣
WebDriverWait wait=new WebDriverWait(driver, new SystemClock(), Sleeper.SYSTEM_SLEEPER, 10, 1000);
實際上,當我們使用後面兩個構造函數的時候,其實也是在默認使用這兩個參數,我們看看WebDriverWait構造函數的源碼
/** * Wait will ignore instances of NotFoundException that are encountered (thrown) by default in * the ‘until‘ condition, and immediately propagate all others. You can add more to the ignore * list by calling ignoring(exceptions to add). * * @param driver The WebDriver instance to pass to the expected conditions * @param timeOutInSeconds The timeout in seconds when an expectation is called * @param sleepInMillis The duration in milliseconds to sleep between polls. * @see WebDriverWait#ignoring(java.lang.Class) */ public WebDriverWait(WebDriver driver, long timeOutInSeconds, long sleepInMillis) { this(driver, new SystemClock(), Sleeper.SYSTEM_SLEEPER, timeOutInSeconds, sleepInMillis); }
懂得第一個構造函數的使用,後面兩個就不啰嗦了,後面兩個實際是在使用默認的參數調用第一個構造函數。
現在我們得到了WebDriverWait對象,怎麽實現等待呢。剛說了,until是當中最重要的一個方法,我們看看WebDriverWait中這個until方法的定義。
public <V> V until(java.util.function.Function<? super WebDriver,V> isTrue) ,
until方法中的參數是一個Function,其中? super WebDriver是參數,表示包括WebDriver在內的所有WebDriver的父類,V是返回值的類型。
例如:
//得到WebDriver WebDriver driver=DriverHelper.CreateChromeDriver(); //定義超時10秒,默認每500毫秒輪詢一次 WebDriverWait wait=new WebDriverWait(driver,10); //重新定義輪詢時間,每隔1秒輪詢一次 wait.pollingEvery(1000, TimeUnit.MILLISECONDS); //忽略NoSuchElementException異常 wait.ignoring(NoSuchElementException.class); //等待10秒,每隔1秒定位一次,直至超時或返回要找的元素 WebElement ele = wait.until(new Function<WebDriver,WebElement>() { @Override public WebElement apply(WebDriver arg0) { // TODO Auto-generated method stub return arg0.findElement(By.id("eleID")); } });
until的參數太復雜,搞不懂?沒關系,官方早已定義了常見的條件。這些條件都在ExpectedConditions這個類中。裏面的方法很多,看名字基本就能猜到用途,官方的文檔為:http://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html
例如:
//得到WebDriver WebDriver driver=DriverHelper.CreateChromeDriver(); //定義超時10秒,默認每500毫秒輪詢一次 WebDriverWait wait=new WebDriverWait(driver,10); //等待直到標題包含abc wait.until(ExpectedConditions.titleContains("abc")); //等待直到元素可點擊 wait.until(ExpectedConditions.elementToBeClickable(By.id("aaa"))); //等待直到url包含cnblogs.com wait.until(ExpectedConditions.urlContains("cnblogs.com"));
更多的預置條件請查看:http://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html
下面通過一個例子,來看看具體怎麽使用。
首先,我們在html文件夾新建一個wait.html,html代碼如下:
<!DOCTYPE html> <html> <head> <meta> <title></title> </head> <body> <input type="text" id="inputID" style="display:none"/> <input type="button" value="點擊" onclick="document.getElementById(‘inputID‘).style.display=‘‘;"/> </body> </html>
然後,我們的代碼要實現的功能是,等待5秒,直到inputID這個文本框顯示,我們就在文本框內輸入“hello,selenium",html中有個按鈕,就是用來控制文本框的顯示隱藏狀態。要實現這個功能,我們需要用到visibilityOfElementLocated(By located)。
代碼如下:
//得到WebDriver WebDriver driver=DriverHelper.CreateChromeDriver(); //跳轉到html driver.get("file:///D:/WorkSpace/SeleniumTest/html/wait.html"); //等待5秒,如果inputID顯示,則輸入"hello,selenium",否則,輸出信息“定位元素超時” WebDriverWait wait=new WebDriverWait(driver, 5); try { wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("inputID"))).sendKeys("hello,selenium"); } catch (RuntimeException e) { System.out.print("定位元素超時!"); }
執行效果如下:
顯式等待-----Selenium快速入門(十)