2017-09-13 7 views
9

ScalaTestのSelenium DSLでSeleniumテストを書いていますが、説明できないタイムアウトに陥っています。事柄をより複雑にするために、それらは時間の一部しか起こらないようです。ScalaTestのSelenium DSLで奇妙なタイムアウトが発生する

この問題は、ページの読み込みやJavaScriptのレンダリング後に要素にアクセスするたびに発生します。それは次のようになります。

click on "editEmployee" 
eventually { 
    textField(name("firstName")).value = "Steve" 
} 

マイPatienceConfigは、このように構成されています

override implicit val patienceConfig: PatienceConfig = 
    PatienceConfig(timeout = Span(5, Seconds), interval = Span(50, Millis)) 

テストは、次のエラーで失敗します。

- should not display the old data after an employee was edited *** FAILED *** 
    The code passed to eventually never returned normally. Attempted 1 times over 10.023253653000001 seconds. 
    Last failure message: WebElement 'firstName' not found.. (EditOwnerTest.scala:24) 

それが成功しないという意味になりますclickがレンダリングを引き起こし、テキストフィールドがすぐに利用できない可能性があるため、すぐに表示されます。しかし、それを見つけようとするのに10秒かかるべきではありませんか?

また、最終的にブロックしたのは一度だけでしたが、ほぼ10秒かかったことは非常に興味深いことです。これは5秒後にタイムアウトに設定されていたため、どこかでタイムアウトが発生したような臭いがあり、PatienceConfigではありません。この回避策では

、それは仕事のことを行います

click on "editEmployee" 
eventually { 
    find(name("firstName")).value // from ScalaTest's `OptionValues` 
} 
textField(name("firstName")).value = "Steve" 

私はいくつかのScalaTestソースに掘った、と私は、この問題を持っているすべてのコールが(それだけtextFieldではありません)、最終的にwebElementを呼び出すことに気付きましたある時点で。回避策が動作する理由は、webElementを呼び出さないためです。 webElementは、このように定義されています

def webElement(implicit driver: WebDriver, pos: source.Position = implicitly[source.Position]): WebElement = { 
    try { 
    driver.findElement(by) 
    } 
    catch { 
    case e: org.openqa.selenium.NoSuchElementException => 
     // the following is avoid the suite instance to be bound/dragged into the messageFun, which can cause serialization problem. 
     val queryStringValue = queryString 
     throw new TestFailedException(
       (_: StackDepthException) => Some("WebElement '" + queryStringValue + "' not found."), 
       Some(e), 
       pos 
       ) 
    } 
} 

私は私のプロジェクトにそのコードをコピーし、それを周りに演奏し、それが構築および/または例外を投げるように見えるしました10秒の大半が費やされているところです。

EDIT解説:暗黙的な待機時間は0に設定されています。また、キャッチブロックを削除すると、すべてが期待どおりに機能します。 )

私の質問は、私はこの奇妙な動作を避けるために何ができますか?私はfindへの余分な呼び出しをいつも挿入する必要はありません。なぜなら、それは簡単には忘れてしまったからです。 (私は動作がいつ発生するのか、いつ動作しないのかを判断できませんでした)

+0

タイムアウトが発生してもページが読み込まれますか?エラーがあるかどうかをブラウザのコンソールで確認しましたか?私の推測では、ページには読み込みに失敗しているリソースがあるため、ページがドライバによって予期される 'complete'状態に達するのを防ぎます。 –

+0

しかし、そうであっても、 'driver.findElement'呼び出しは暗黙の待ち時間が0に設定されているので失敗し、catchブロックに移動してから' finally'を実行すると再び試行されます。 – jqno

+0

暗黙の待機設定は影響を与えず、ページが完了するのを待つことには関係しません。ドライバは、 'pageLoadingStrategy'が' none'に設定されていない限り、各コマンドでページ[完了状態](https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState)を待ちます。 。 –

答えて

1

明らかに、textField(name("firstName")).value = "Steve"は、あなたが見つけたとおりにWebElementと呼ばれることがあります。 オペレーションの問題は、Web要素が関わっているところで起こっているので(Webdriverが関与していることを意味します)、Webドライバの暗黙の待機に関連していると考えるのが安全だと思います。

implicitlyWait(Span(0, Seconds)) 

上記は理想的には問題を解決するはずです。また、暗黙の待ちを0にすることは悪い習慣です。どのWebページにも負荷がかかる可能性があります。ページの読み込みは、待ち状態の外でSeleniumによって処理されます。しかし、遅い要素の負荷(ajax呼び出しによるものかもしれません)は失敗に終わる可能性があります。私は通常、暗黙のスタンダードとして10秒間保持します。より多くの待機を必要とするシナリオでは、明示的な待機を使用できます。

def implicitlyWait(timeout: Span)(implicit driver: WebDriver): Unit = { 
driver.manage.timeouts.implicitlyWait(timeout.totalNanos, TimeUnit.NANOSECONDS) 
} 

実行フロー:

name("firstName")Query {Val by = By.className("firstName") }として値を有するしまいます。

def name(elementName: String): NameQuery = new NameQuery(elementName) 

case class NameQuery(queryString: String) extends Query { val by = By.name(queryString) } 
Query

として以下Query.webElementを呼び出しtextField方法に供給されます。

def textField(query: Query)(implicit driver: WebDriver, pos: source.Position): TextField = new TextField(query.webElement)(pos) 

sealed trait Query extends Product with Serializable { 

    val by: By 

    val queryString: String 

    def webElement(implicit driver: WebDriver, pos: source.Position = implicitly[source.Position]): WebElement = { 
     try { 
     driver.findElement(by) 
     } 
     catch { 
     case e: org.openqa.selenium.NoSuchElementException => 
      // the following is avoid the suite instance to be bound/dragged into the messageFun, which can cause serialization problem. 
      val queryStringValue = queryString 
      throw new TestFailedException(
        (_: StackDepthException) => Some("WebElement '" + queryStringValue + "' not found."), 
        Some(e), 
        pos 
        ) 
     } 
    } 
    } 
+0

'implicitlyWait'タイムアウトを増やすと助けになります!ありがとう!悲しいことに、私はこの賞金が切れる前にこの答えを得ることができませんでした。 – jqno

0

ScalaTestの仕様はわかりませんが、通常、このような奇妙なタイムアウトは暗黙的および明示的な待機を混在させるときに発生します。

driver.findElementは内部的に暗黙の待機を使用します。また、指定された明示的待ち時間のタイムアウトに応じて、両方を合計することで直面することがあります。

理想的には、このような問題を回避するには、暗黙の待機を0に設定する必要があります。

+0

提案していただきありがとうございますが、暗黙の待機が0に設定されていました。 – jqno

+0

要素をクリック可能にするまで待機する明示的待機を使用してください。 –

関連する問題