web-dev-qa-db-ja.com

Webドライバーでページが完全にロードされているかどうかを確認するにはどうすればよいですか?

Javaアプリケーションを自動化するWebdriverコードを書いています。ページがロードされたかどうかを正しく確認するにはどうすればよいですか?アプリケーションにはいくつかのAjax呼び出しもあります。

WebDriverの暗黙的な待機を宣言しました。

21
Raghubansh

セレンはあなたのためにそれを行います。または、少なくとも最善を尽くします。時には不足することもありますので、少し手伝ってください。通常の解決策は Implicit Wait これはほとんどの問題を解決します。

あなたが何をしていて、なぜそれをしているのかを本当に知っている場合、あなたはを試して、ページが完全にロードされます。ただし、すべてのWebおよびすべての状況に対応できるわけではありません。


関連質問: Selenium WebDriver:JavaScript(JS)を含む複雑なページがロードされるのを待ちます 、そこに私の答えを参照してください。

短いバージョン:確実ではありません。

「通常の」ロードは簡単です- document.readyState 。もちろん、これはSeleniumによって実装されています。問題は、AJAXの非同期リクエストです。これは、完了したかどうかを判断できないためです。今日のほとんどのWebページには、永久に実行され、常にサーバーをポーリングするスクリプトがあります。

あなたができるさまざまなことは、上記のリンクの下にあります。または、他の人の95%と同様に、 Implicit Wait 暗黙的および Explicit Wait + ExpectedConditions 必要な場所。

例えば。クリック後、ページ上のいくつかの要素が表示されるようになり、それを待つ必要があります。

WebDriverWait wait = new WebDriverWait(driver, 10);  // you can reuse this one

WebElement elem = driver.findElement(By.id("myInvisibleElement"));
elem.click();
wait.until(ExpectedConditions.visibilityOf(elem));
35
Petr Janeček

ロードされると設定されるJavaScript変数をWepPageに設定できます。どこにでも置くことができますが、jQueryを使用している場合、$(document).onReadyは開始するのに悪い場所ではありません。そうでない場合は、<script>タグはページの下部にあります。

要素の可視性をチェックするのではなく、このメソッドの利点は、waitステートメントの実行後にページの正確な状態を知ることができることです。

MyWebPage.html

... All my page content ...
<script> window.TestReady = true; </script></body></html>

そして、あなたのテスト(C#の例)で:

// The timespan determines how long to wait for any 'condition' to return a value
// If it is exceeded an exception is thrown.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5.0));

// Set the 'condition' as an anonymous function returning a boolean
wait.Until<Boolean>(delegate(IWebDriver d)
{
    // Check if our global variable is initialized by running a little JS
    return (Boolean)((IJavaScriptExecutor)d).ExecuteScript("return typeof(window.TestReady) !== 'undefined' && window.TestReady === true");
});
3
jmathew

シンプルready2useスニペット、私にとって完璧に動作

static void waitForPageLoad(WebDriver wdriver) {
    WebDriverWait wait = new WebDriverWait(wdriver, 60);

    Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver input) {
            return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
        }

    };
    wait.until(pageLoaded);
}
2
NarendraC

私はこの投稿が古いことを知っています。しかし、上記からすべてのコードを収集した後、Ajaxの実行中のページと通常のページを処理するNiceメソッド(ソリューション)を作成しました。コードはC#専用に作成されています(Seleniumは1年いじり回した後、C#Visual Studioに最適です)。

このメソッドは、拡張メソッドとして使用されます。つまり、シンプルにすることを意味します。この場合、オブジェクトIWebDriverにさらに機能(メソッド)を追加できます。重要なのは、それを利用するためにパラメーターで「this」を定義する必要があることです。

タイムアウト変数は、ページが応答しない場合にWebdriverが待機する秒数です。 'Selenium'および 'Selenium.Support.UI'名前空間を使用すると、ブール値を返すjavascriptの一部を実行できます。これは、ドキュメントが準備完了(完全)かどうか、jQueryがロードされているかどうかです。ページにjQueryがない場合、メソッドは例外をスローします。この例外は、エラー処理によって「キャッチ」されます。 catch状態では、ドキュメントはjQueryを確認せずに、準備完了状態のみを確認します。

public static void WaitUntilDocumentIsReady(this IWebDriver driver, int timeoutInSeconds) {
    var javaScriptExecutor = driver as IJavaScriptExecutor;
    var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));

    try {
        Func<IWebDriver, bool> readyCondition = webDriver => (bool)javaScriptExecutor.ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
        wait.Until(readyCondition);
    } catch(InvalidOperationException) {
        wait.Until(wd => javaScriptExecutor.ExecuteScript("return document.readyState").ToString() == "complete");
    }
}
1
Bedirhan

コードスニペットを使用して基本的なアイデアを提供し、修正する方法を次に示します。

public class IFrame1 extends LoadableComponent<IFrame1> {

    private RemoteWebDriver driver;

    @FindBy(id = "iFrame1TextFieldTestInputControlID" ) public WebElement iFrame1TextFieldInput;
    @FindBy(id = "iFrame1TextFieldTestProcessButtonID" ) public WebElement copyButton;

    public IFrame1( RemoteWebDriver drv ) {
        super();
        this.driver = drv;
        this.driver.switchTo().defaultContent();
        waitTimer(1, 1000);
        this.driver.switchTo().frame("BodyFrame1");
        LOGGER.info("IFrame1 constructor...");
    }

    @Override
    protected void isLoaded() throws Error {        
        LOGGER.info("IFrame1.isLoaded()...");
        PageFactory.initElements( driver, this );
        try {
            assertTrue( "Page visible title is not yet available.", 
                    driver.findElementByCssSelector("body form#webDriverUnitiFrame1TestFormID h1")
                    .getText().equals("iFrame1 Test") );
        } catch ( NoSuchElementException e) {
            LOGGER.info("No such element." );
            assertTrue("No such element.", false);
        }
    }

    /**
     * Method: load
     * Overidden method from the LoadableComponent class.
     * @return  void
     * @throws  null
     */
    @Override
    protected void load() {
        LOGGER.info("IFrame1.load()...");
        Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring( NoSuchElementException.class ) 
                .ignoring( StaleElementReferenceException.class ) ;
        wait.until( ExpectedConditions.presenceOfElementLocated( 
                By.cssSelector("body form#webDriverUnitiFrame1TestFormID h1") ) );
    }
....
0
djangofan

最近、AJAX application/RIAを扱っていたとき、私は同じ問題を抱えていました!そして、約90秒の時間で暗黙的な待機を使用しました。利用できる...だから、そのページが完全にロードされることを確認するためにできることは、

条件(要素の特定の部分)が存在するかどうかを確認するブール文を追加して変数に割り当て、条件を確認し、それがtrueの場合にのみ、「必要なアクションを実行してください!」...このようにして、両方の待機を使用できることがわかりました...

例:

@Before

{ implicit wait statement}

@Test

{

boolean tr1=Driver.findElement(By.xpath("xx")).isEnabled/isDisplayed;

if (tr1==true && ____)//as many conditions, to make sure, the page is loaded

{

//do the necessary set of actions...
driver.findElement(By.xpath("yy")).click();

}

}

お役に立てれば!!私にとっても実装段階です...

0
Mannii88

以下は、待機用のBasePageObjectクラスのコードです。

public void waitForPageLoadAndTitleContains(int timeout, String pageTitle) {
    WebDriverWait wait = new WebDriverWait(driver, timeout, 1000);
    wait.until(ExpectedConditions.titleContains(pageTitle));
}

public void waitForElementPresence(By locator, int seconds) {
    WebDriverWait wait = new WebDriverWait(driver, seconds);
    wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}

public void jsWaitForPageToLoad(int timeOutInSeconds) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    String jsCommand = "return document.readyState";

    // Validate readyState before doing any waits
    if (js.executeScript(jsCommand).toString().equals("complete")) {
        return;
    }

    for (int i = 0; i < timeOutInSeconds; i++) {
        TimeManager.waitInSeconds(3);
        if (js.executeScript(jsCommand).toString().equals("complete")) {
            break;
        }
    }
}

   /**
     * Looks for a visible OR invisible element via the provided locator for up
     * to maxWaitTime. Returns as soon as the element is found.
     *
     * @param byLocator
     * @param maxWaitTime - In seconds
     * @return
     *
     */
    public WebElement findElementThatIsPresent(final By byLocator, int maxWaitTime) {
        if (driver == null) {
            nullDriverNullPointerExeption();
        }
        FluentWait<WebDriver> wait = new FluentWait<>(driver).withTimeout(maxWaitTime, Java.util.concurrent.TimeUnit.SECONDS)
                .pollingEvery(200, Java.util.concurrent.TimeUnit.MILLISECONDS);

        try {
            return wait.until((WebDriver webDriver) -> {
                List<WebElement> elems = driver.findElements(byLocator);
                if (elems.size() > 0) {
                    return elems.get(0);
                } else {
                    return null;
                }
            });
        } catch (Exception e) {
            return null;
        }
    }

サポート方法:

     /**
     * Gets locator.
     *
     * @param fieldName
     * @return
     */
    public By getBy(String fieldName) {
        try {
            return new Annotations(this.getClass().getDeclaredField(fieldName)).buildBy();
        } catch (NoSuchFieldException e) {
            return null;
        }
    }
0
Mykola

スクリーンショットを撮って、レンダリングされたページを場所に保存し、ページが完全に読み込まれ、破損した画像がない場合は、スクリーンショットを確認できます