27

私はSelenium WebDriverが初めてで、要素が存在するのを「待つ」正しい方法を理解しようとしています。

ラジオボタンの回答を持つ一連の質問でページをテストしています。回答を選択すると、Javascript によって、ページ上のいくつかの質問が有効または無効になる場合があります。

問題は、Selenium の「クリックが速すぎる」ことであり、Javascript が終了するのを待っていないようです。私はこの問題を 2 つの方法で解決しようとしました - 明示的な待機が問題を解決しました。具体的には、これは機能し、私の問題を解決します:

private static WebElement findElement(final WebDriver driver, final By locator, final int timeoutSeconds) {
    FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
            .withTimeout(timeoutSeconds, TimeUnit.SECONDS)
            .pollingEvery(500, TimeUnit.MILLISECONDS)
            .ignoring(NoSuchElementException.class);

    return wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver webDriver) {
            return driver.findElement(locator);
        }
    });
}

ただし、これの代わりに暗黙の待機を使用することをお勧めします。Web ドライバーを次のように構成しました。

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

これで問題は解決せず、NoSuchElementException が発生します。さらに、10 秒間の一時停止に気付かず、ただちにエラーになります。コードのこの行がデバッガーでヒットしていることを確認しました。私は何を間違っていますか?要素が表示されるのを暗黙的に待機しないのに、FluentWait が待機するのはなぜですか?

注: 前述したように、既に回避策がありますが、Implicit wait で問題が解決しない理由を知りたいだけです。ありがとう。

4

9 に答える 9

27

いくつかのシナリオには違いがあることに注意してください。

  • DOM にまったく存在しない要素。
  • DOM に存在するが表示されない要素。
  • DOM に存在するが有効になっていない要素。(つまり、クリック可能)

私の推測では、ページの一部が JavaScript で表示されている場合、要素はブラウザー DOM に既に存在していますが、表示されていません。暗黙の待機は要素が DOM に現れるのを待つだけなので、すぐに戻りますが、要素を操作しようとすると NoSuchElementException が発生します。要素が表示またはクリック可能になるのを明示的に待機するヘルパー メソッドを作成することで、この仮説をテストできます。

いくつかの例 (Java):

public WebElement getWhenVisible(By locator, int timeout) {
    WebElement element = null;
    WebDriverWait wait = new WebDriverWait(driver, timeout);
    element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
    return element;
}

public void clickWhenReady(By locator, int timeout) {
    WebDriverWait wait = new WebDriverWait(driver, timeout);
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(locator));
    element.click();
}
于 2013-01-25T10:19:39.883 に答える
3

基本的な考え方は次のとおりです。

明示的な待機

WebDriverWait.until(condition-that-finds-the-element);

暗黙の待機

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

言い換えれば、明示的は保持される条件に関連付けられていますが、暗黙的は何かを待つ時間に関連付けられています。 このリンクを参照してください

fluentWait を適切に機能させるには、次のようにします。

public WebElement fluentWait(final By locator){
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
        .withTimeout(Duration.ofSeconds(30))
        .pollingEvery(Duration.ofMillis(100))
        .ignoring(NoSuchElementException.class);

    WebElement foo = wait.until(
        new Function<WebDriver, WebElement>() {
            public WebElement apply(WebDriver driver) {
                return driver.findElement(locator);
            }
        }
    );
    return foo;
};

お役に立てれば)

于 2012-09-05T15:16:19.440 に答える
2

よくある間違いに対する警告:

暗黙的な待機を設定すると、暗黙的な待機を再度リセットするまで、明示的な待機または流暢な待機を使用できません。これはExpectedConditions、呼び出しを含むdriver.findElementが暗黙の待機で期待どおりに機能しないことを意味します! 要素が存在するか、存在しないかをすぐに確認したい場合によく遭遇しますが、それもできません。

〜2年間の経験とこれに関する問題の後、暗黙の待機を使用しないことを強くお勧めします。

于 2015-11-11T09:43:15.480 に答える
1

https://stackoverflow.com/users/503060/hedleyの回答の kotlin バージョン:

clickWhenReady("#suggest",10,driver)

経由

fun clickWhenReady(selector: String,timeout: Long, webdriver: WebDriver?) {
    val wait = WebDriverWait(webdriver, timeout);
    val element = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(selector)));
    element.click();
}
于 2016-08-09T16:34:09.557 に答える
0

WebDriverWait クラスを使用して C# で小さなメソッドを作成しました。私にとってはうまくいきます。

public static void WaitForAjaxElement(IWebDriver driver, By byElement, double timeoutSeconds)
{
  WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutSeconds));
  wait.Until(x => x.FindElement(byElement));
}

使用:

WaitForAjaxElement(driver, By.ClassName("ui-menu-item"), 10);

それが役に立てば幸い。

于 2012-08-22T13:17:59.830 に答える
0

Seleniumhq.com から:

暗黙の待機とは、要素がすぐに利用できない場合に要素を見つけようとするときに、WebDriver に一定時間 DOM をポーリングするように指示することです。デフォルト設定は 0 です。一度設定すると、暗黙的な待機が WebDriver オブジェクト インスタンスの存続期間にわたって設定されます。

実際にやりたいことをテストコードを投稿すると、より多くの情報を提供できます。

于 2012-08-22T13:23:24.257 に答える