2013-12-09 9 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

実際にFluentWaitがタイムアウトすると、TimeoutExceptionを抑制することはできません。それは単にAPIの性質です。これが本当に無視したい例外の場合は、TimeoutExceptionにキャッチする必要があります。

また、サイドノートとして、ナノ秒ごとに条件をポーリングしようとするのは逆効果である可能性があります。おそらくポーリング間隔を200ミリ秒や250ミリ秒ごとに延長する必要があります。

1

この問題がなぜ発生するのかを知るために必要な重要な手がかりをJim Evansに与えてくれてありがとう。

FluentWaitコード(Java 1.8以降)を調べて、Throwされないようにリクエストしても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方法を見てください。その可能性が高いすべての例外処理/投げロジックがある可能性があります。 withTimeout,など、FluentWaitの他のメソッド呼び出しは、実際にFluentWaitオブジェクトの「設定」を作成します。待機中やコード実行中などの操作は実行されません。

documentation for "until"を見てみましょう。最後の行は、このメソッドがTimeoutExceptionをスローすることを示しています。したがって、あなたがリクエストしたとしても、untilメソッドはTimeoutExceptionを無視してはなりません。

Throws: 
TimeoutException - If the timeout expires. 

「until」がTimeoutExceptionを無視しない理由を理解するためにFluentWaitのコードをすぐに調べます。

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. 返り "値" 変数、OR
  2. はあなたが無視されるように要求しなかったすべての例外を伝播します。 (propagateIfNotIgnoredメソッド呼び出しを参照してください)。

例外が伝播されない場合、ifブロックが実行されます。タイムアウトが発生すると、TimeoutExceptionがスローされます。つまり、タイムアウト例外の原因となるコードのビットです。

+1

コードがどのように「複雑」なのかよく分かりません。 timeoutが評価されると( 'if(!clock.isNowBefore(end))')、timeoutが期限切れになった場合、 'timeoutException()'という名前のクラス内の別のメソッドから返された値である 'TimeoutException'を投げます。 。このメソッドは、前の例外処理ブロックでキャッチされた実際の例外を引数として取り込みます。このコードブロックはtry-catchの外にあり、指定された型の例外を無視するコードの影響を受けないことに注意してください。 – JimEvans

+0

@ JimEvans - ありがとう。あまりにも早く反応した。私は静かにしてコードをすばやくスキャンし、自分の答えを編集しました。コードは私が思ったほど難解ではありません。 – testerjoe2

関連する問題