143

ページが完全に読み込まれるまでセレンを待機させるにはどうすればよいですか? WebDriverWait を構成し、「find」などを呼び出して待機させることができることはわかっていますが、そこまでは行きません。ページが正常に読み込まれることをテストし、次のページに移動してテストする必要があります。

.net で何かを見つけましたが、Java で動作させることができませんでした ...

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));

誰か考えはありますか?

4

27 に答える 27

98

提案された解決策は、DOMreadyStateがシグナルを送るのを待つだけcompleteです。driver.get()しかし、Selenium はデフォルトで、メソッドとメソッドを介してページの読み込み時にそれら (およびもう少し) を待機しようとしelement.click()ます。それらはすでにブロックされており、ページが完全に読み込まれるのを待っており、正常に機能するはずです。

問題は、明らかに、AJAX リクエストと実行中のスクリプトを介したリダイレクトです。これらは Selenium でキャッチできず、終了するのを待ちません。また、それらを経由して確実にキャッチすることはできませんreadyState-少し待機しますが、これは便利ですが、completeすべてのAJAXコンテンツがダウンロードされるずっと前に通知されます.

どこでも、誰にとっても有効な一般的な解決策はありません。それが難しい理由で、誰もが少しずつ異なるものを使用しています。

一般的なルールは、WebDriver に自分の役割を任せてから、暗黙的な待機を使用してから、ページでアサートしたい要素に対して明示的な待機を使用することですが、実行できる手法は他にもたくさんあります。テストしたページで、自分の場合に最適な 1 つ (または複数の組み合わせ) を選択する必要があります。

詳細については、これに関する私の 2 つの回答を参照してください。

于 2013-02-28T13:08:52.827 に答える
84

このコードを試してください:

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

上記のコードは、ページの読み込みを最大 10 秒待機します。ページの読み込みが時間を超えると、TimeoutException. 例外をキャッチして、必要なことを行います。例外がスローされた後にページの読み込みを終了するかどうかはわかりません。私はまだこのコードを試していません。試してみたいだけです。

これは暗黙の待機です。これを一度設定すると、Web Driver インスタンスが破棄されるまでスコープが保持されます。

詳細については、ドキュメントをWebDriver.Timeouts参照してください。

于 2013-02-28T04:14:06.767 に答える
69

これは、あなたが与えた例の動作するJavaバージョンです:

void waitForLoad(WebDriver driver) {
    new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
            ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
}

例 c# の場合:

public static void WaitForLoad(IWebDriver driver, int timeoutSec = 15)
{
    IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
    WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
    wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
}

PHP の例:

final public function waitUntilDomReadyState(RemoteWebDriver $webDriver): void
{
    $webDriver->wait()->until(function () {
        return $webDriver->executeScript('return document.readyState') === 'complete';
    });
}
于 2013-02-27T23:25:39.403 に答える
7
WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));
于 2016-06-09T06:19:18.417 に答える
3

最初のページの読み込みでは、ブラウザウィンドウを「最大化」すると、ページの読み込みが完了するまで実際に待機することに気付きました(ソースを含む)

交換:

AppDriver.Navigate().GoToUrl(url);

と:

public void OpenURL(IWebDriver AppDriver, string Url)
            {
                try
                {
                    AppDriver.Navigate().GoToUrl(Url);
                    AppDriver.Manage().Window.Maximize();
                    AppDriver.SwitchTo().ActiveElement();
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERR: {0}; {1}", e.TargetSite, e.Message);
                    throw;
                }
            }

使用より:

OpenURL(myDriver, myUrl);

これにより、ページが読み込まれ、完了するまで待機し、最大化してフォーカスします。なぜこのようになるのかわかりませんが、うまくいきます。

次をクリックした後、または「Navigate()」以外の他のページナビゲーショントリガーをクリックした後にページの読み込みを待ちたい場合は、Ben Dyer の回答 (このスレッド) が機能します。

于 2015-06-04T06:56:15.200 に答える
2

Nodejsでは、約束を介して取得できます...

このコードを記述すれば、次のページに到達したときにページが完全に読み込まれていることを確認できます...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

このコードを書くと、ナビゲートされ、セレンは 3 秒待機します...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

セレンのドキュメントから:

this.get( url ) → その後可能

指定された URL に移動するコマンドをスケジュールします。

ドキュメントの読み込みが完了したときに解決される promise を返します。

Selenium ドキュメント (Nodejs)

于 2016-12-23T15:50:57.137 に答える
1

タペストリーWeb フレームワークをご覧ください。そこからソースコードをダウンロードできます。

アイデアは、本文の html 属性によってページの準備ができていることを知らせることです。このアイデアを使用して、複雑な訴訟を無視できます。

<html>
<head>
</head>
<body data-page-initialized="false">
    <p>Write you page here</p>

    <script>
    $(document).ready(function () {
        $(document.body).attr('data-page-initialized', 'true');
    });
    </script>  
</body>
</html>

次に、Selenium webdriver の拡張機能を作成します (タペストリー フレームワークに従って)

public static void WaitForPageToLoad(this IWebDriver driver, int timeout = 15000)
{
    //wait a bit for the page to start loading
    Thread.Sleep(100);

    //// In a limited number of cases, a "page" is an container error page or raw HTML content
    // that does not include the body element and data-page-initialized element. In those cases,
    // there will never be page initialization in the Tapestry sense and we return immediately.
    if (!driver.ElementIsDisplayed("/html/body[@data-page-initialized]"))
    {                
        return;
    }

    Stopwatch stopwatch = Stopwatch.StartNew();

    int sleepTime = 20;

    while(true)
    {
        if (driver.ElementIsDisplayed("/html/body[@data-page-initialized='true']"))
        {
            return;
        }

        if (stopwatch.ElapsedMilliseconds > 30000)
        {
            throw new Exception("Page did not finish initializing after 30 seconds.");
        }

        Thread.Sleep(sleepTime);
        sleepTime *= 2; // geometric row of sleep time
    }          
}

Alister Scott によって作成された拡張 ElementIsDisplayed を使用します。

public static bool ElementIsDisplayed(this IWebDriver driver, string xpath)
{
    try
    {
        return driver.FindElement(By.XPath(xpath)).Displayed;
    }
    catch(NoSuchElementException)
    {
        return false;
    }
}

そして最後にテストを作成します:

driver.Url = this.GetAbsoluteUrl("/Account/Login");            
driver.WaitForPageToLoad();
于 2016-06-06T08:13:59.050 に答える
1

このコードを試してみましたが、うまくいきました。別のページに移動するたびにこの関数を呼び出します

public static void waitForPageToBeReady() 
{
    JavascriptExecutor js = (JavascriptExecutor)driver;

    //This loop will rotate for 100 times to check If page Is ready after every 1 second.
    //You can replace your if you wants to Increase or decrease wait time.
    for (int i=0; i<400; i++)
    { 
        try 
        {
            Thread.sleep(1000);
        }catch (InterruptedException e) {} 
        //To check page ready state.

        if (js.executeScript("return document.readyState").toString().equals("complete"))
        { 
            break; 
        }   
      }
 }
于 2016-08-12T18:47:39.570 に答える
1

Ben Dryer の回答は、私のマシンではコンパイルされませんでした ( "The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait")。

動作中の Java 8 バージョン:

Predicate<WebDriver> pageLoaded = wd -> ((JavascriptExecutor) wd).executeScript(
        "return document.readyState").equals("complete");
new FluentWait<WebDriver>(driver).until(pageLoaded);

Java 7 バージョン:

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

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

};
new FluentWait<WebDriver>(driver).until(pageLoaded);
于 2016-06-21T20:59:49.043 に答える
0

ドキュメントの準備ができているかどうかを確認するために JavaScript コードを実行しました。クライアント側のレンダリングを行うサイトのセレン テストをデバッグする時間を大幅に節約できました。

public static boolean waitUntilDOMIsReady(WebDriver driver) {
def maxSeconds = DEFAULT_WAIT_SECONDS * 10
for (count in 1..maxSeconds) {
    Thread.sleep(100)
    def ready = isDOMReady(driver);
    if (ready) {
        break;
    }
}

}

public static boolean isDOMReady(WebDriver driver){
    return driver.executeScript("return document.readyState");
}
于 2016-08-11T00:26:55.763 に答える
0

次のコードはおそらく機能するはずです。

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfAllElementsLocated(By.xpath("//*")));
于 2017-12-01T07:35:56.943 に答える
-1

Ruby で似たようなものを次に示します。

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { @driver.execute_script('return document.readyState').eql?('complete') }
于 2015-04-24T21:18:44.373 に答える