暗黙的および明示的な待機 Selenium 構文付き

⚡ スマートサマリー

Selenium Wait コマンドは、自動化スクリプトを動的なページ動作と同期させ、非同期で読み込まれる要素によって引き起こされるテストの失敗を防ぎます。このリファレンスでは、WebDriver 構文を使用した暗黙的、明示的、および流暢な Wait 戦略について説明します。 Java コードサンプル、および安定した信頼性の高いテスト実行のために適切な待機時間を選択するための実践的なガイダンス。

  • ⚙️ Foundation原則: Implicit Waitをグローバルに適用することで、WebDriverがNoSuchElementExceptionを発生させる前に、定義された期間だけ一時停止するようにします。
  • 🎯 実装の焦点: ExpectedConditions と Explicit Wait を使用して、Ajax や動的な表示状態に依存する要素を対象とするようにします。
  • 🔁 高度なテクニック: Fluent Waitをポーリング間隔で設定することで、読み込みタイミングが予測できない要素にも対応できます。
  • 最適化戦略: 実行時間を短縮し、不安定な遅延を排除するために、Thread.sleep を条件付き待機に置き換えてください。
  • 品質への影響: 適切な待機時間を選択することで、不安定な障害を直接的に減らし、環境を跨いだスクリプトの安定性を向上させることができます。

Selenium 待機 – 構文による暗黙的および明示的

In Selenium「待機」は、信頼性の高いテストを実行する上で重要な役割を果たします。このチュートリアルでは、暗黙的待機コマンドと明示的待機コマンドの主な側面と違いについて学びます。 Seleniumさらに、Fluent Waitの実践的な使用方法についても解説します。

なぜ待機が必要なのか Selenium?

現代のウェブアプリケーションのほとんどは、 アヤックス (NAIST) と Javaスクリプトブラウザがページを読み込む際、操作したい要素は異なる時間間隔で読み込まれる可能性があります。

これにより要素の識別が困難になるだけでなく、要素が時間内に見つからない場合、 Selenium を投げます ElementNotVisibleException. Selenium 待機処理は、WebDriverに要素を見つけるための一定の時間枠を与えることで、この同期問題を解決します。時間枠が確保できない場合は、WebDriverは要素を見つけることができません。

暗黙的な待機と明示的な待機の両方が同じテストで使用されるシナリオを考えてみましょう。暗黙的な待機は20秒、明示的な待機は10秒に設定されているとします。

特定の条件に支配される要素を探している場合 予想される条件 (明示的待機)要素が明示的な10秒のウィンドウ内にない場合、WebDriverは20秒の暗黙的なウィンドウにフォールバックしてから例外をスローします。 ElementNotVisibleException.

Selenium WebDriverが待機します

  1. 暗黙的な待機
  2. 明示的な待機
  3. 流暢な待機

暗黙的な待機 Selenium

その 暗黙的な待機 Selenium WebDriverに対し、指定された期間待機してからNoSuchElementExceptionをスローするように指示します。デフォルト値は0です。設定が完了すると、WebDriverはその期間中DOMをポーリングし、その後エラーが発生します。 Selenium WebDriverは暗黙の待機の概念を継承しました Watir.

以下の例では、10秒間の暗黙的な待機を宣言しています。要素がその時間内に存在しない場合、例外が発生します。

暗黙の待機構文 (Selenium 4):

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
package guru.test99;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;

public class AppTest {

    protected WebDriver driver;

    @Test
    public void guru99tutorials() throws InterruptedException {
        driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
        String eTitle = "Demo Guru99 Page";
        String aTitle = "";
        // launch Chrome and redirect it to the Base URL
        driver.get("https://demo.guru99.com/test/guru99home/");
        // Maximize the browser window
        driver.manage().window().maximize();
        // get the actual value of the title
        aTitle = driver.getTitle();
        // compare the actual title with the expected title
        if (aTitle.equals(eTitle)) {
            System.out.println("Test Passed");
        } else {
            System.out.println("Test Failed");
        }
        // close browser
        driver.close();
    }
}

の説明 Code

上記の例では、次の文を考えてみましょう。

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));

Selenium バージョン4では、以前の2つの引数(整数とTimeUnit)を持つシグネチャが、単一のDuration引数に置き換えられました。Durationクラスは、Duration.ofSeconds、Duration.ofMillis、Duration.ofMinutesなどの静的ヘルパーを通じて、秒、分、ミリ秒、およびその他の時間単位をサポートします。

明示的な待機 Selenium

その 明示的な待機 Selenium WebDriverに対し、特定の条件(期待される条件)が満たされるか、最大期間が経過するまで待機してからElementNotVisibleExceptionをスローするように指示します。これは、指定された要素にのみ適用されるため、よりスマートな待機方法です。テストで動的に読み込まれるAjaxコンテンツを処理する必要がある場合は、暗黙的な待機よりも明示的な待機が推奨されます。

明示的な待機が宣言されたら、 予想される条件または、ポーリング頻度は次のように設定できます。 流暢な待機使用を避ける Thread.sleep()これは無条件に実行を一時停止させるため、一般的に好ましくない方法とみなされています。

以下の例では、 WebDriverWait クラスをインスタンス化して、 webdriver 参照し、最大ウィンドウを20秒に設定します。

明示的な待機構文 (Selenium 4):

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
package guru.test99;

import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.Test;

public class AppTest2 {
    protected WebDriver driver;

    @Test
    public void guru99tutorials() throws InterruptedException {
        driver = new ChromeDriver();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
        String eTitle = "Demo Guru99 Page";
        String aTitle = "";
        // launch Chrome and redirect it to the Base URL
        driver.get("https://demo.guru99.com/test/guru99home/");
        // Maximize the browser window
        driver.manage().window().maximize();
        // get the actual value of the title
        aTitle = driver.getTitle();
        // compare the actual title with the expected title
        if (aTitle.contentEquals(eTitle)) {
            System.out.println("Test Passed");
        } else {
            System.out.println("Test Failed");
        }
        WebElement guru99seleniumlink;
        guru99seleniumlink = wait.until(ExpectedConditions.visibilityOfElementLocated(
            By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
        guru99seleniumlink.click();
    }
}

の説明 Code

次のコードについて考えてみます。

WebElement guru99seleniumlink;
guru99seleniumlink = wait.until(ExpectedConditions.visibilityOfElementLocated(
    By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
guru99seleniumlink.click();

この WebDriverWait の例では、スクリプトは、 WebDriverWait クラス、 予想される条件 満足したか、どちらか早い方。

上記 Java コードは条件を満たすまで最大20秒間待機します 要素の位置の可視性 TRUEにする。

以下の期待条件は、 Selenium 明示的な待機:

  1. アラートは存在します()
  2. elementSelectionStateToBe()
  3. elementToBeClickable()
  4. elementToBeSelected()
  5. フレームToBeAvailableAndSwitchToIt()
  6. invisibilityOfTheElementLocated()
  7. invisibilityOfElementWithText()
  8. presentOfAllElementsLocatedBy()
  9. presentOfElementLocated()
  10. textToBePresentInElement()
  11. textToBePresentInElementLocated()
  12. textToBePresentInElementValue()
  13. タイトルは()
  14. titleContains()
  15. 可視性Of()
  16. すべての要素の可視性()
  17. 可視性OfAllElementsLocatedBy()
  18. 可視性OfElementLocated()

流暢な待機 Selenium

その 流暢な待機 Selenium WebDriverが条件を満たすまで待機する最大時間と、ElementNotVisibleExceptionをスローする前にその条件を確認するためのポーリング頻度を定義します。Fluent Waitは、オブジェクトが見つかるかタイムアウトになるまで、一定間隔で要素をチェックします。

対応周波数: 定期的な間隔で状態を評価するための繰り返しサイクル。

要素の読み込み間隔が予測できないシナリオを考えてみましょう。要素の読み込みには10秒、20秒、あるいはそれ以上かかる場合があります。明示的に20秒の待機時間を指定すると、スクリプトは指定された時間いっぱいまで待機してからエラーになります。このような場合、Fluent Waitは理想的な選択肢です。要素が見つかるか、最終タイマーが期限切れになるまで、指定された頻度でポーリングを行うからです。

流暢な待機構文(Selenium 4):

Wait<WebDriver> wait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(30))
    .pollingEvery(Duration.ofSeconds(5))
    .ignoring(NoSuchElementException.class);

整数値と TimeUnit を受け入れる古い署名は、 Selenium 3.11で削除されました Selenium 4. 上記に示した期間ベースのAPIは、現在推奨されている方法です。

package guru.test99;

import java.time.Duration;
import java.util.NoSuchElementException;
import java.util.function.Function;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.testng.annotations.Test;

public class AppTest3 {
    protected WebDriver driver;

    @Test
    public void guru99tutorials() throws InterruptedException {
        String eTitle = "Demo Guru99 Page";
        String aTitle = "";
        driver = new ChromeDriver();
        // launch Chrome and redirect it to the Base URL
        driver.get("https://demo.guru99.com/test/guru99home/");
        // Maximize the browser window
        driver.manage().window().maximize();
        // get the actual value of the title
        aTitle = driver.getTitle();
        // compare the actual title with the expected title
        if (aTitle.contentEquals(eTitle)) {
            System.out.println("Test Passed");
        } else {
            System.out.println("Test Failed");
        }

        Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(Duration.ofSeconds(30))
            .pollingEvery(Duration.ofSeconds(5))
            .ignoring(NoSuchElementException.class);

        WebElement clickseleniumlink = wait.until(new Function<WebDriver, WebElement>() {
            public WebElement apply(WebDriver driver) {
                return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
            }
        });
        // click on the selenium link
        clickseleniumlink.click();
        // close browser
        driver.close();
    }
}

の説明 Code

次のコードについて考えてみます。

Wait<WebDriver> wait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(30))
    .pollingEvery(Duration.ofSeconds(5))
    .ignoring(NoSuchElementException.class);

上記の例では、タイムアウト30秒、ポーリング頻度5秒、無視するFluent Waitを宣言しています。 NoSuchElementException.

次のコードについて考えてみます。

public WebElement apply(WebDriver driver) {
    return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
}

この関数はページ上の WebElement (ここでは、 Selenium ホームページのリンク)。ポーリング間隔が 5 秒、タイムアウトが 30 秒の場合、待機は最大 30 秒間、5 秒ごとに要素をチェックします。要素がその時間内に存在すれば、スクリプトは続行されます。そうでなければ、 ElementNotVisibleException 投げられます。

チェック: Selenium 初心者向け IDE チュートリアル

暗黙的な待機と明示的な待機の違い

以下の表は、暗黙的待機と明示的待機の主な違いを示しています。 Selenium.

暗黙的な待機 明示的な待機
スクリプト内のすべての要素に暗黙の待機時間が適用されます。 明示的な待機時間は、特に対象とした要素にのみ適用されます。
暗黙的待機では、要素に対して ExpectedConditions は指定されません。 明示的待機では、要素に対して ExpectedConditions を定義する必要があります。
要素が設定された暗黙の待機時間内に読み込まれる場合に推奨されます。 要素の読み込みに時間がかかる場合や、可視性(要素の位置特定)、クリック可能な要素、選択可能な要素などの要素の状態を検証する場合に推奨されます。
一度設定すれば、WebDriverインスタンスのライフサイクル全体に適用されます。 要素ごと、またはチェックごとに設定できるため、よりきめ細かな制御が可能になります。

適切な待機戦略の選び方

適切な待機コマンドを選択することは、スクリプトの安定性と実行時間に直接影響します。この判断基準を用いて、各シナリオに適したオプションを選択してください。

  1. 負荷パターンを特定する: 要素がAjax応答後、固定時間に表示されるのか、それとも予測不可能な間隔で表示されるのかを確認してください。固定時間での読み込みには暗黙的待機が適していますが、予測不可能な読み込みには流暢な待機が必要です。
  2. 暗黙的待機と明示的待機を混在させないでください。 この2つを組み合わせると、待ち時間が長くなる方が優先されるため、予期せぬ遅延が発生する可能性があります。 Selenium ドキュメントでは、WebDriverセッションごとに1つの戦略のみを使用することを推奨しています。
  3. 動的コンテンツに対して、デフォルトで明示的な待機を行う: ページがAjax、条件付きレンダリング、またはアニメーションに依存している場合、ExpectedConditionsを使用した明示的待機は、重要な要素を正確にターゲットにします。
  4. 可変タイミングにはFluent Waitを使用してください。 要素の読み込みタイミングが実行ごとに異なる場合は、Fluent Wait をポーリング間隔で設定してください。ポーリングは、単一の長いタイムアウトと比較して、合計の待機時間を短縮します。
  5. Thread.sleep を置き換えます: ハードコードされたスリープはテストスイートの実行速度を低下させ、実際のタイミングの問題を隠蔽します。実行速度と実行の決定性を維持するために、条件付き待機に置き換えてください。
  6. タイムアウト値を調整します。 最初は短いタイムアウト(5~10秒)から始め、実際に負荷が遅いことが障害の原因となっている場合にのみタイムアウトを長くしてください。デフォルトのタイムアウトが長すぎると、パフォーマンスの低下が隠蔽されてしまいます。
  7. ヘルパーユーティリティで待機処理を保持する: タイムアウト処理のロジックをヘルパークラスに集約することで、タイムアウトポリシーの変更がテストスイート全体に適用されるようにします。

このフレームワークに従うことで、自動化エンジニアは、実際のアプリケーションのタイミングに適応しつつ、動作が遅くなったり不安定になったりしない、堅牢なスクリプトを構築できます。

避けるべきよくある間違い Selenium 待つ

経験豊富なテスターでさえ、 Selenium 待機時間が発生します。これらの問題を回避することで、スクリプトは高速で、決定論的で、チームや環境を問わず容易に保守できるようになります。

よくある間違いの1つは、Thread.sleep の使いすぎです。ハードコードされた一時停止は、実際の要素の利用可能性に関係なく、スクリプトが指定された時間だけ待機することを強制するため、実行時間が長くなります。このような一時停止は、明示的待機または流暢な待機に置き換えて、条件が満たされた瞬間にスクリプトが実行されるようにしてください。

2つ目の間違いは、暗黙的待機と明示的待機を同じテスト内で混在させることです。これら2つのメカニズムが複合的に作用し、デバッグが困難な予測不能なタイムアウトが発生する可能性があります。WebDriverセッションごとに1つの戦略を選択し、一貫して適用してください。

3つ目の間違いは、「念のため」タイムアウトを長く設定しすぎることです。デフォルトのタイムアウト時間が長すぎると、実際のパフォーマンスの問題が隠蔽され、継続的インテグレーションパイプラインのフィードバックが遅くなります。最初は短いタイムアウトから始め、エラーログで実際のタイミングの問題が証明された場合にのみ延長するようにしてください。

チェック: Selenium 初心者向けチュートリアル: 7 日間で WebDriver を学ぶ

よくあるご質問

デフォルトの暗黙の待機時間は Selenium WebDriver の待機時間は 0 秒です。カスタムの Duration 値を指定して implicitlyWait メソッドが呼び出されるまで、ドライバーは要素が見つからない場合でも一時停止しません。

Thread.sleep は、要素の準備状況に関係なく、一定時間、無条件に実行を一時停止します。そのため、全体の実行時間が増加し、パフォーマンスの問題が隠蔽され、テストが不安定になります。明示的待機と流暢な待機は、条件が満たされた瞬間に実行を再開します。

お勧めしません。 Selenium ドキュメントには、両方を組み合わせると予測不能な待ち時間が発生する可能性があると警告されています。WebDriverセッションごとに、通常は明示的待機または流暢な待機のいずれか1つの戦略を選択することで、動作がより明確になり、デバッグが容易になります。

はい。AI駆動型テストプラットフォームなど TestimMablやFunctionizeは、アプリケーションの応答時間を分析し、明示的待機値または流暢な待機値を推奨します。これにより、試行錯誤による調整を減らし、観測されたページ動作に基づいてタイムアウトを動的に調整します。

AIエンジンは過去の負荷パターンを学習し、ポーリング間隔やタイムアウトウィンドウを自動的に調整します。テストがタイミング境界付近で繰り返し失敗した場合、モデルは待機時間を延長するか、より賢明な条件に切り替えることで、実行全体を通して不安定な失敗を減らします。