2013-12-09 36 views
5

我有自動它通過http://www.efinancialcareers.co.uk/search此頁轉到一些用戶流量。 當我使用左側精煉導軌縮小搜索範圍時,會出現疊加層,用戶必須等待直到搜索結果返回。該方法等待疊加層出現,然後等待它消失。的webdriver FluentWait沒有忽略例外

public void waitForSRPOverlayToComplete() { 

    Wait<WebDriver> wait = new FluentWait<WebDriver>(getDriver()) 
      .withTimeout(5, TimeUnit.SECONDS) 
      .pollingEvery(1, TimeUnit.NANOSECONDS) 
      .ignoring(NoSuchElementException.class) 
      .ignoring(TimeoutException.class); 

    **// Error occurs here** 
    WebElement blockedOverlay = wait.until(new Function<WebDriver, WebElement>() { 
     public WebElement apply(WebDriver driver) { 
      return driver.findElement(By.className("blockOverlay")); 
     } 
    }); 

    Wait<WebDriver> wait2 = new FluentWait<WebDriver>(getDriver()) 
      .withTimeout(5, TimeUnit.SECONDS) 
      .pollingEvery(1, TimeUnit.NANOSECONDS) 
      .ignoring(NoSuchElementException.class) 
      .ignoring(TimeoutException.class); 

    wait2.until(ExpectedConditions.stalenessOf(blockedOverlay)); 
} 

有時我得到一個超時異常的元素(blockOverlay)未找到。當這種情況發生時,我觀察了頁面,覆蓋層確實出現了,但我認爲有時當搜索非常快時,上述方法會錯過它。 我不明白爲什麼我會遇到技術錯誤,因爲我已經說了一口流利的等待忽略它們。

這是爲了覆蓋的代碼出現:

$('body').block({ 
      message: $('#loaderEl'), 
      css: { 
       backgroundColor: 'transparent', 
       border: "none", 
       color: '#333333', 
       fontWeight: 'bolder', 
       top: ($(window).height() - $('#loaderEl').height())/2 + $(window).scrollTop() + "px" 
      }, 
      overlayCSS: { 
       backgroundColor: '#f8f8f8' 
      }, 
      centerY: false 
     }); 

,並刪除它

$('body').unblock(); 

這是錯誤我收到:

Caused by: org.openqa.selenium.TimeoutException: Timed out after 5 seconds waiting for  [email protected] 
Build info: version: '2.35.0', revision: '8df0c6bedf70ff9f22c647788f9fe9c8d22210e2',  time: '2013-08-17 12:46:41' 
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_26' 
Driver info: driver.version: unknown 
    ... 33 more 
Caused by: org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"class name","selector":"blockOverlay"} 

任何幫助或建議將不勝感激。

回答

8

您不能取消TimeoutException出來的時候,其實FluentWait倍。這只是API的性質。如果這是一個你真正想忽略的例外,你需要趕上TimeoutException

此外,作爲一個側面說明,試圖輪詢條件每納秒很可能適得其反。您應該延長輪詢時間間隔,例如每200或250毫秒。

1

非常感謝吉姆·埃文斯給我我需要知道爲什麼會出現此問題的關鍵線索。

我決定通過挖掘到FluentWait代碼走得更遠(Java 1.8或更高版本),看看爲什麼即使你要求它不被拋出TimeoutException異常被拋出。 FluentWait的

典型的例子:

 WebDriver driver = new ChromeDriver(); 

     FluentWait wait = new FluentWait(driver) 
       .withTimeout(30, TimeUnit.SECONDS) 
       .pollingEvery(5, TimeUnit.SECONDS) 
       .ignoring(NoSuchElementException.class); 

     WebElement foo = (WebElement) wait.until(new Function() { 
      @Override 
      public WebElement apply(Object input) { 
       return null; 
      } 
     }); 

我們看看FluentWait的until方法,因爲這是真正開始等待過程中的方法。它可能是所有的異常處理/投擲邏輯可能在那裏。 FluentWait的所有其他方法調用,例如withTimeout,ignoring等實際上爲FluentWait對象創建「設置」。他們不執行像等待或運行某些代碼等

讓我們來看看documentation for "until"任何行動。最後一行告訴我們該方法拋出一個TimeoutException。所以,即使你要求,until方法也不應該忽略TimeoutException。

Throws: 
TimeoutException - If the timeout expires. 

我們現在趕緊來看看FluentWait的代碼來理解爲什麼「直到」不忽略TimeoutException異常。

public <V> V until(Function<? super T, V> isTrue) { 
    long end = clock.laterBy(timeout.in(MILLISECONDS)); 
    Throwable lastException = null; 
    while (true) { 
     try { 
     V value = isTrue.apply(input); 
     if (value != null && Boolean.class.equals(value.getClass())) { 
      if (Boolean.TRUE.equals(value)) { 
      return value; 
      } 
     } else if (value != null) { 
      return value; 
     } 
     } catch (Throwable e) { 
     lastException = propagateIfNotIgnored(e); 
     } 

     // Check the timeout after evaluating the function to ensure conditions 
     // with a zero timeout can succeed. 
     if (!clock.isNowBefore(end)) { 
     String message = messageSupplier != null ? 
      messageSupplier.get() : null; 

     String toAppend = message == null ? 
      " waiting for " + isTrue.toString() : ": " + message; 

     String timeoutMessage = String.format("Timed out after %d seconds%s", 
      timeout.in(SECONDS), toAppend); 
     throw timeoutException(timeoutMessage, lastException); 
     } 

     try { 
     sleeper.sleep(interval); 
     } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
     throw new WebDriverException(e); 
     } 
    } 
    } 

的,而塊將:

  1. 回報「值」變量或
  2. 傳播你沒有請求被忽略任何異常。 (參見propagateIfNotIgnored方法調用,這個名字使它明顯,你可以看到代碼,以及確認。)

的,如果在沒有傳播的異常塊將運行。如果發生超時,它會引發TimeoutException。所以,這是負責超時異常的代碼。

+1

我不知道我是如何看到代碼「複雜」的。當超時被評估('if(!clock.isNowBefore(end))'')時,如果超時已經到期,則拋出'TimeoutException',這是另一個創造性地稱爲'timeoutException()'的類中的方法返回的值。 。該方法將傳播的實際異常作爲參數,該異常由前一個異常處理塊捕獲。請注意,此代碼塊位於任何try-catch之外,因此不受忽略給定類型的異常的代碼影響。 – JimEvans

+0

@JimEvans - 謝謝。我反應過快。我保持冷靜,迅速掃描了代碼並編輯了我的答案。代碼並不像我想的那樣難以理解。 – testerjoe2