1. 程式人生 > >顯式等待-----Selenium快速入門(十)

顯式等待-----Selenium快速入門(十)

edr gif tex 通過 輸出信息 except 顯式 eve span

  上一篇說了元素定位過程中的隱式等待,今天我們來探討一下顯示等待。顯式等待,其實就是在使用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快速入門(十)