web-dev-qa-db-ja.com

JavaでSelenium-WebDriverに数秒間待つように依頼するにはどうすればよいですか?

私はJava Selenium-WebDriverに取り組んでいます。追加した

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

そして

WebElement textbox = driver.findElement(By.id("textbox"));

私のアプリケーションはユーザーインターフェースをロードするのに数秒かかるからです。だから私は2秒を暗黙的に設定しました。しかし要素のテキストボックスを見つけることができませんでした

それから私はThread.sleep(2000);を追加します

今ではうまくいきます。どちらが良い方法ですか?

95
Prince

待機には、明示的待機と暗黙的待機の2種類があります。明示的待機のアイデアは

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(30, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class);

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

    return  foo;
};

fluentWait関数は、見つかったWeb要素を返します。 fluentWaitのドキュメントから:タイムアウトとポーリング間隔がその場で設定されるかもしれないWaitインタフェースの実装。各FluentWaitインスタンスは、条件を待機する最大時間と条件をチェックする頻度を定義します。さらに、ユーザーは、ページ上の要素を検索するときのNoSuchElementExceptionsなど、待機中に特定の種類の例外を無視するように待機を設定できます。ここで得られる詳細情報

あなたの場合のfluentWaitの使い方は次のとおりです。

WebElement textbox = fluentWait(By.id("textbox"));

あなたが正確にどれだけの時間待つべきかわからないし、ポーリング間隔であなたがどの要素の存在が検証されるかについて任意の時間値を設定することができるので、このアプローチは私見よりも優れています。よろしく。

111

WebdriverJs(node.js)を使用している場合は、

driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
    driver.sleep(5000);
});

上記のコードは、ボタンをクリックした後ブラウザに5秒間待たせます。

16
Anup

このスレッドは少し古いですが、私が現在行っていること(進行中の作業)を投稿したいと思いました。

システムに大きな負荷がかかっているときや、送信ボタンをクリックしたとき(login.jspなど)には、依然として3つの条件(true)が返されますが、次のページ(home.jsp)は返されません。まだロードを開始していません。

これはExpectedConditionsのリストを受け取る一般的なwaitメソッドです。

public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
    boolean isLoaded = false;
    Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(waitTimeInSec, TimeUnit.SECONDS)
            .ignoring(StaleElementReferenceException.class)
            .pollingEvery(2, TimeUnit.SECONDS);
    for (ExpectedCondition<Boolean> condition : conditions) {
        isLoaded = wait.until(condition);
        if (isLoaded == false) {
            //Stop checking on first condition returning false.
            break;
        }
    }
    return isLoaded;
}

私はさまざまな再利用可能なExpectedConditionを定義しました(3つは以下です)。この例では、document.readyState = 'complete'、no "wait_dialog"、および 'spinners'(非同期データが要求されていることを示す要素)が含まれています。

最初のものだけがすべてのWebページに一般的に適用できます。

/**
 * Returns 'true' if the value of the 'window.document.readyState' via
 * JavaScript is 'complete'
 */
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
        Boolean result;
        try {
            result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
        } catch (Exception ex) {
            result = Boolean.FALSE;
        }
        return result;
    }
};
/**
 * Returns 'true' if there is no 'wait_dialog' element present on the page.
 */
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
            WebElement wait = driver.findElement(By.id("F"));
            if (wait.isDisplayed()) {
                loaded = false;
            }
        } catch (StaleElementReferenceException serex) {
            loaded = false;
        } catch (NoSuchElementException nseex) {
            loaded = true;
        } catch (Exception ex) {
            loaded = false;
            System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
        }
        return loaded;
    }
};
/**
 * Returns true if there are no elements with the 'spinner' class name.
 */
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
        List<WebElement> spinners = driver.findElements(By.className("spinner"));
        for (WebElement spinner : spinners) {
            if (spinner.isDisplayed()) {
                loaded = false;
                break;
            }
        }
        }catch (Exception ex) {
            loaded = false;
        }
        return loaded;
    }
};

ページに応じて、それらの1つまたはすべてを使用することがあります。

waitForPageLoad(timeoutInSec,
            EXPECT_DOC_READY_STATE,
            EXPECT_NOT_WAITING,
            EXPECT_NO_SPINNERS
    );

次のクラスには、定義済みのExpectedConditionもあります。 org.openqa.Selenium.support.ui.ExpectedConditions

12
Jeff Vincent

Thread.sleep(2000);の使用は無条件の待機です。テストのロードが早くなっても、まだ待つ必要があります。したがって、原則としてimplicitlyWaitを使用することがより良い解決策です。

しかし、implicitlyWaitがあなたのケースでうまくいかない理由はわかりません。 findElementが実際に例外をスローする前に2秒かかるかどうかを測定しましたか。もしそうなら、 this の答えで説明されているように、WebDriverの条件付き待機を使うことを試みることができますか?

9
Valentin

私はカスタム条件を使うのが好きです。これがPythonのコードです。

def conditions(driver):
    flag = True
    ticker = driver.find_elements_by_id("textbox")
    if not ticker:
        flag = False
    return flag

... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)

待つ必要があるときはいつでも、特定の要素の存在を確認することによって明示的にそれを行うことができます(そのような要素はページごとに異なる場合があります)。 find_elements_by_idはリストを返します - 空かどうかは、あなたがチェックするだけです。

3
simno

クリックがブロックされているように見える? - WebDriverJSを使用しているかどうかを確認するもう1つの方法があります。

driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
  driver.getPageSource().then(function(source) {
    console.log(source);
  });
});

上記のコードは、ボタンがクリックされて次のページがロードされるのを待ってから、次のページのソースを取得します。

2
Dion
Thread.Sleep(5000);

これは役に立ちましたが、InterruptedException例外を処理する必要があります。そのため、try and catchで囲んでください。

try {
    Thread.Sleep(5000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

OR

スロー宣言を追加します。

public class myClass {
    public static void main(String[] args) throws InterruptedException
    { ... }

sleep()が必要なだけ何度でも使用でき、sleep()が使用されるたびにtryおよびcatchブロックが繰り返されるのを避けることができるので、2番目の方法をお勧めします。

1
Prasad Hajare

暗黙のwaitが失敗することもあり、要素は存在するが実際には存在しないと言っています。

解決策は、driver.findElementを使用せずに、暗黙的にExplicit Waitを使用するカスタムメソッドに置き換えることです。例えば:

import org.openqa.Selenium.NoSuchElementException;


public WebElement element(By locator){
    Integer timeoutLimitSeconds = 20;
    WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
    try {
        wait.until(ExpectedConditions.presenceOfElementLocated(locator));
    }
    catch(TimeoutException e){
        throw new NoSuchElementException(locator.toString());
    }
    WebElement element = driver.findElement(locator);
    return element;
}

散発的で偶発的な失敗以外に暗黙の待機を回避するための追加の理由があります(こちら リンク を参照)。

この "element"メソッドをdriver.findElementと同じ方法で使用できます。例えば:

    driver.get("http://yoursite.html");
    element(By.cssSelector("h1.logo")).click();

トラブルシューティングやその他のまれな場合に数秒間待つだけの場合は、Selenium IDEのような一時停止方法を作成できます。

    public void pause(Integer milliseconds){
    try {
        TimeUnit.MILLISECONDS.sleep(milliseconds);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
0
JohnP2

暗黙的に待機とThread.sleep両方とも同期のみに使用されますが、違いはプログラム全体を暗黙的に待機させることですが、Thread.sleepはその単一のコードに対してのみ機能します。あなたのWebページが更新されるたびにその時Thread.sleepを使用することを意味します..それははるかに良いでしょう:)

これが私のコードです:

package beckyOwnProjects;

import Java.util.concurrent.TimeUnit;

import org.openqa.Selenium.By;
import org.openqa.Selenium.WebDriver;
import org.openqa.Selenium.WebElement;
import org.openqa.Selenium.firefox.FirefoxDriver;
import org.openqa.Selenium.interactions.Actions;

public class Flip {

    public static void main(String[] args) throws InterruptedException {
        WebDriver driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
        driver.get("https://www.flipkart.com");
    WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
    Actions act=new Actions(driver);
    Thread.sleep(5000);
    act.moveToElement(ele).perform();
    }

}
0
Beckham Vinoth

暗黙の待機がオーバーライドされ、待機時間が短縮されることがあります。 [@ eugene.polschikov]は、whysに関する優れたドキュメントを持っていました。私のSelenium 2でのテストとコーディングでは、暗黙的な待機は有効であることがわかりましたが、場合によっては明示的に待機する必要があります。

直接スレッドをスリープさせることを避けた方が良いですが、時にはそれを回避する良い方法がありません。しかし、他にもSeleniumが提供する待機オプションがあります。 waitForPageToLoadwaitForFrameToLoadが特に便利です。

0
BadgerAndK

答え:Selenium WebDriverを使用した要素の可視性が以下の方法を通過する前に数秒待ってください。

implicitlyWait():WebDriverインスタンスは全ページがロードされるまで待機します。あなたは全ページロードを待つのに30から60秒を使います。

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

ExplicitlyWait WebDriverWait():WebDriverインスタンスは全ページがロードされるまで待機します。

WebDriverWait wait = new WebDriverWait(driver, 60);

wait.until(ExpectedConditions.visibilityOf(textbox));

driver.findElement(By.id("Year")).sendKeys(allKeys);

:特定のWebElementを処理するにはExplicitlyWait WebDriverWait()を使用してください。

0
sandeep shewale

暗黙的待機:暗黙的待機中に、Webドライバがその可用性のためにすぐにそれを見つけることができない場合、WebDriverは指定された時間待機し、指定された期間中に再び要素を見つけようとしません。指定された時間が終わると、例外をスローする前に最後にもう一度要素を検索しようとします。デフォルト設定はゼロです。時間を設定すると、WebドライバはWebDriverオブジェクトインスタンスの期間を待ちます。

明示的な待機:特定の要素がロードに1分以上かかる場合があります。その場合、あなたがブラウザをすべての要素に対して同じ時間だけ待つように、暗黙の待ち時間に莫大な時間を設定するのは嫌です。そのような状況を避けるために、あなたは単に必要な要素だけに別々の時間を置くことができます。これに従うことによってあなたのブラウザの暗黙の待ち時間はあらゆる要素のために短くなり、それは特定の要素のために大きくなるでしょう。

0
Abhishek Singh