4

すべてのページのインスタンス化でいくつかのことを行っている間、DOM との Selenium の相互作用は非常に遅いようです。サイト全体で、未解決の API 呼び出しが解決されたかどうかを示すスピナーが表示されます。要約すると、アクションを実行する前にページの安定性を確認する 3 つの方法があります。

  1. DOM の準備完了状態を確認する
  2. 未解決の JQuery 呼び出しがないか確認する
  3. スピナーの読み込みを確認する

これら 3 つのすべては、次のメソッドを使用してページ オブジェクトのインスタンス化の一部として実行されます。

    public static void waitForLoadingAllSpinnersAnywhere(final WebDriver driver){
    final WebDriverWait wait = new WebDriverWait(driver, timeout);
    
    wait.until(waitForDomReadyState());
    wait.until(waitForjQueryToBeInactive());
    List<WebElement> elements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(spinnersLoacator));
    
    for(WebElement element: elements){
        wait.until(invisibilityOfElementLocated(element));  
     }
    }

    private static ExpectedCondition<Boolean> waitForDomReadyState(){

        return new ExpectedCondition<Boolean>() {

            @Override
            public Boolean apply(WebDriver d){

                return ( ((JavascriptExecutor) d).executeScript("return document.readyState;").equals("complete"));
            }
        };
    }


    private static ExpectedCondition<Boolean> waitForjQueryToBeInactive(){

        return new ExpectedCondition<Boolean>() {

            @Override
            public Boolean apply(WebDriver d){

                return (Boolean) ( ((JavascriptExecutor) d).executeScript("return jQuery.active == 0;"));
            }
        };
    }

    public static ExpectedCondition<Boolean> invisibilityOfElementLocated(final WebElement element){

        return new ExpectedCondition<Boolean>() {

            @Override
            public Boolean apply(WebDriver driver){

                try{
                    return !element.isDisplayed();
                } catch (NoSuchElementException | StaleElementReferenceException e){
                    // Returns true because the element is not present in DOM.
                    // The
                    // try block checks if the element is present but is
                    // invisible or stale
                    return true;
                }
            }
        };
    }

かなりの数の API 呼び出しがあり、大量のデータをフェッチするページ (患者ページなど) を例にとります。最初のクラスのインスタンス化には、約 17 秒かかります (以下のログ)。私の Selenium の知識によると、後続のページのインスタンス化では、DOM の準備完了状態を確認するのに同じまたはそれ以上の時間がかかるべきではありません。また、JQuery の呼び出しまたはスピナーの待機は、何も変更されていないためです。ただし、新しいページがインスタンス化されるたびに、これら 3 つすべてをチェックするのに同じ時間がかかることがわかります。そこで何が起こっているのですか?Selenium は実際にこれらを実行するたびにサーバーと対話しようとしますか、それともクライアントとの対話が何らかの理由で遅いですか? もしそうなら、可能な答えは何ですか?

コンソールログ

==== [[[17]秒後にウィジェット[患者]で見つかった8つのスピナー要素の待機を終了しました]]

==== [[ウィジェット [患者] で見つかった 8 つのスピナー要素の待機を開始します]]

==== [[[17]秒後にウィジェット[患者]で見つかった8つのスピナー要素の待機を終了しました]]

==== [[[Patient]]] のブラウザ

==== [[ウィジェット [患者] で見つかった 8 つのスピナー要素の待機を開始します]]

==== [[[17]秒後にウィジェット[患者]で見つかった8つのスピナー要素の待機を終了しました]]

環境:

  1. セレン 2.48
  2. Firefox 38

Selenium 2.52 と firefox 44 でも同じ結果で試しました

4

2 に答える 2

5

Selenium は、条件が満たされるまで、評価ごとにサーバーにリクエストを送信することで、クライアント側でのすべての待機を処理します。レイテンシーが高い場合、特に多くの呼び出しがある場合は、すぐに劣化する可能性があります。さらに、一部の評価ではスクリプト インジェクションが必要ですが、どちらも役に立ちません。

したがって、この場合のパフォーマンスを改善する最善の方法は、単一の非同期 JavaScript 呼び出しを使用することです。

public static void waitForLoadingAllSpinnersAnywhere(final WebDriver driver) {
  const String JS_WAIT_SPINNERS = 
      "var callback = arguments[0]; " +
      "(function fn(){ " +
      "  if (document.readyState == 'complete' && jQuery.active == 0) { " +
      "    var elts = $('.spinners'); " +
      "    if (elts.length == 8 && !elts.is(':visible')) " +
      "      return callback(); " +
      "  } " +
      "  setTimeout(fn, 60); " +
      "})();";

   ((JavascriptExecutor)driver).executeAsyncScript(JS_WAIT_SPINNERS);
}

タイムアウトを初期化するには:

driver.manage().timeouts().setScriptTimeout(30, TimeUnit.SECONDS);
于 2016-03-07T03:17:04.240 に答える
3

あなたのテストはすべてのnon-native呼び出しであるように見えるので、Firefox はあなたのために働くはずですが、44 と 48 を使用していた場合、driver.navigate() への Firefox ネイティブ呼び出しが最初のページに到達するためにさえ働いたことに驚いています。 31.6.0 がサポートされている最後のネイティブ Firefox バージョンであることがわかっています。ですから、これを理解するまでは Chrome を使用する必要があります。

しかし、遅さについてあなたのことに答えるために。あなたがコードを書いた方法は、jQuery に大きく依存しており、jQuery コードへの呼び出しが遅延し、Selenium テストに伝播し、複数のループをループしているという事実によってさらに影響を受けるという問題があると思います。スピナー。前に気づいたことの 1 つは、ページが ajax 呼び出しの実行でビジー状態の場合、JavascriptExecutor を使用した Selenium 呼び出しは、それらがプロセッサ時間を少し放棄するのを待つ必要があるかもしれないということです。

どうすればいいですか?ええと、jQuery に対して JavascriptExecutors を呼び出す代わりに、DOM で動作するようにスピナーの待機を記述します。おそらくあなたの場合、これはオプションではありませんが、よく考えられた計画により、ページの準備が整ったワークフローの効率を向上させることができると思います.

于 2016-03-01T19:50:14.280 に答える