Warten Sie auf das Laden der Seite in Selen


Antworten:


138

Sie können pageloaded auch mit dem folgenden Code überprüfen

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"));

22
Sie würden denken, dass so etwas eingebaut wäre. Das Warten auf das Laden von Seiten ist im Web eine ziemlich häufige Sache.
PRMan

19
funktioniert das wirklich die ganze Zeit? Vielleicht fehlt mir etwas in Ihrem Code, aber Sie warten darauf, dass der Dom bereit ist. Beachten Sie jedoch, dass die vorherige Seite möglicherweise noch nicht entladen wird, wenn Ihr Code zu schnell ausgeführt wird, und true zurückgibt, obwohl Sie sich noch auf der alten Seite befinden. Warten Sie, bis die aktuelle Seite entladen ist, und rufen Sie dann den obigen Code auf. Eine Möglichkeit, das Entladen von Seiten zu erkennen, besteht darin, ein Webelement auf der aktuellen Seite abzurufen und zu warten, bis es veraltet ist. obeythetestinggoat.com/…
George

6
Zu Ihrer Information - Auch wenn das oben Gesagte noch nicht garantiert, dass die Seite vollständig ist - nur, dass der Dom bereit ist. Jedes Dojo / jede Abfrage erstellt möglicherweise weiterhin dynamisch Elemente auf der Seite, sodass Sie möglicherweise zuerst auf dynamische Elemente warten müssen, bevor Sie mit ihnen interagieren können.
George

3
Beachten Sie, dass diese Methode nur das DOM überprüft. Wenn Sie Ajax oder AngularJS verwenden, funktioniert dies nicht, da einige asynchrone Aufrufe vom document.readyState nicht erkannt werden.
Homewrecker

3
Dies ist C # -Code. Dies funktioniert nicht mit Java und die Frage zu Java .
Kingamere

89

Verwenden Sie die Klasse WebDriverWait

Siehe auch hier

Sie können erwarten, ein Element zu zeigen. so etwas wie in C #:

WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));

_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));

Das hat super geklappt. Es ist eine sehr schöne moderne Art, das Problem zu lösen.
CrazyDart

3
@ EmmanuelAngelo.R TimeSpan ist eine .Net-Datenstruktur.
rjzii

12
Was ist, wenn ich nicht weiß, welches Element auf der Seite angezeigt wird?
JustGoscha

3
Dies funktioniert, um auf das Laden eines bestimmten Elements und nicht auf die gesamte Seite zu warten.
XYZ

1
Dies garantiert überhaupt nicht, dass ein Element vollständig geladen ist, und beantwortet auch nicht die Frage. Wie kann jemand dem zustimmen?
Boris D. Teoharov

36

Wenn Sie die implizite Wartezeit des Treibers festlegen und dann die findElementMethode für ein Element aufrufen, von dem Sie erwarten, dass es sich auf der geladenen Seite befindet, fragt der WebDriver nach diesem Element, bis er das Element findet oder den Zeitlimitwert erreicht.

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

Quelle: implizite Wartezeiten


3
Es hilft nicht, auf das Laden der Seite zu warten.
XYZ

Dies bedeutet, dass 10 Sekunden lang etwas versucht wird, bevor eine Ausnahme ausgelöst wird. Daher kann nicht sichergestellt werden, dass die Verzögerung 10 Sekunden dauert.
Skysign

1
@xyz - warum hilft es nicht?
MasterJoe2

@ testerjoe2 Es wartet, bis ein bestimmtes Element gefunden wurde. Die Frage ist, wie auf das Laden der Seite gewartet werden soll.
XYZ

35

Im Allgemeinen sollte der Webtreiber mit Selenium 2.0 die Kontrolle über den aufrufenden Code erst zurückgeben, wenn festgestellt wurde, dass die Seite geladen wurde. Wenn dies nicht der Fall ist, können Sie anrufen waitforelemement, wodurch der Anruf wiederholt wird, findelementbis er gefunden wird oder eine Zeitüberschreitung auftritt (Zeitüberschreitung kann eingestellt werden).


2
Hinzufügen zu Pauls Antwort. Bitte überprüfen Sie dies auch auf stackoverflow.com/questions/5858743/… .
9ikhan

27
Leider wartet Selenium 2 nicht in allen Fällen auf das Laden einer Seite. Zum Beispiel wartet WebElement: click () nicht und dies wird im zugehörigen Javadoc ausdrücklich gesagt. Sie sagen jedoch nicht, wie ich prüfen kann, ob eine neue Seite geladen wird. If click() causes a new page to be loaded via an event or is done by sending a native event (which is a common case on Firefox, IE on Windows) then the method will not wait for it to be loaded and the caller should verify that a new page has been loaded.
Sebi

Von doc ..und die Methode wird blockieren, bis der Ladevorgang abgeschlossen ist ...
xyz

2
@ Karna: Ja, theoretisch sollte es immer und in der Praxis meistens. Die Verwendung von Selenium zu der Zeit hat gezeigt, dass es Zeiten gab, in denen angenommen wurde, dass die Seite vollständig geladen wurde, dies jedoch nicht. Ich habe in letzter Zeit nicht viel Selen verwendet, daher kann dies immer noch der Fall sein oder auch nicht.
Paul Hadfield

3
Ich stimme zu: Insbesondere der Internet Explorer-Treiber ist fehlerhaft und gibt in einigen Fällen sofort die Kontrolle zurück, obwohl eine Seite noch geladen wird. In meinem Fall habe ich eine Wartezeit mit hinzugefügt JavascriptExecutorund darauf gewartet, dass document.readyState "vollständig" ist. Aufgrund der Hin- und Rückfahrt von Selen zum Browser wird der Rennzustand vermutlich gemildert, und dies funktioniert "immer" für mich. Nach "click ()", wenn ich erwarte, dass eine Seite geladen wird, warte ich explizit (mit WebDriverWait) auf den Readystate. ]
Dmansfield

21

Ruby-Implementierung:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}

17
Python-Äquivalent: WebDriverWait (Treiber, 10). Bis (Lambda d: d.execute_script ('return document.readyState') == 'complete')
Blaze

2
Python verwendet den obigen Code, aber vergessen Sie diese Zeile nicht .. | von
selenium.webdriver.support.ui

Ich hatte ein Problem beim Klicken auf ein Element, als die Seite nicht vollständig geladen war. In Python habe ich time.sleep (30) ausprobiert. Es funktionierte. Es wird jedoch immer auf die maximalen 30 Sekunden warten. Ich habe dann den folgenden Code ausprobiert und er ist jetzt effizienter und schneller. WebDriverWait (Treiber, 10). Bis (lambda d: driver.find_element_by_xpath ("// div [. = 'Administration']"). Click ())
Riaz Ladhani

20

Sie können die System.outZeile entfernen . Es wird zu Debug-Zwecken hinzugefügt.

WebDriver driver_;

public void waitForPageLoad() {

    Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
    wait.until(new Function<WebDriver, Boolean>() {
        public Boolean apply(WebDriver driver) {
            System.out.println("Current Window State       : "
                + String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
            return String
                .valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
                .equals("complete");
        }
    });
}

Danke für diese Tipps. Ich füge es meinem SeleniumHelper hinzu. vgl. javabox
boly38

17

Alle diese Lösungen sind für bestimmte Fälle in Ordnung, leiden jedoch unter mindestens einem von mehreren möglichen Problemen:

  1. Sie sind nicht allgemein genug - sie möchten, dass Sie im Voraus wissen, dass eine bestimmte Bedingung für die Seite gilt, auf die Sie gehen (z. B. wird ein Element angezeigt).

  2. Sie sind offen für eine Race-Bedingung, bei der Sie ein Element verwenden, das sowohl auf der alten als auch auf der neuen Seite vorhanden ist.

Hier ist mein Versuch einer generischen Lösung, die dieses Problem vermeidet (in Python):

Zunächst eine generische "Warte" -Funktion (verwenden Sie ein WebDriverWait, wenn Sie möchten, ich finde sie hässlich):

def wait_for(condition_function):
    start_time = time.time()
    while time.time() < start_time + 3:
        if condition_function():
            return True
        else:
            time.sleep(0.1)
    raise Exception('Timeout waiting for {}'.format(condition_function.__name__))

Als nächstes beruht die Lösung auf der Tatsache, dass Selen eine (interne) ID-Nummer für alle Elemente auf einer Seite aufzeichnet, einschließlich der obersten Ebene <html> Elements . Wenn eine Seite aktualisiert oder geladen wird, erhält sie ein neues HTML-Element mit einer neuen ID.

Angenommen, Sie möchten auf einen Link mit dem Text "Mein Link" klicken, zum Beispiel:

old_page = browser.find_element_by_tag_name('html')

browser.find_element_by_link_text('my link').click()

def page_has_loaded():
    new_page = browser.find_element_by_tag_name('html')
    return new_page.id != old_page.id

wait_for(page_has_loaded)

Für mehr pythonische, wiederverwendbare, generische Hilfsmittel können Sie einen Kontextmanager erstellen:

from contextlib import contextmanager

@contextmanager
def wait_for_page_load(browser):
    old_page = browser.find_element_by_tag_name('html')

    yield

    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id

    wait_for(page_has_loaded)

Und dann können Sie es für so ziemlich jede Selen-Wechselwirkung verwenden:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

Ich denke, das ist kugelsicher! Was denken Sie?

Mehr Infos in einem Blogbeitrag dazu hier


Ich habe Ihre Webseite gelesen, bevor ich erneut genauer nach Java-Code gesucht habe, der Ihre Lösung implementiert. Bisher nichts ...
Andrew Lorien

11

Sie können auch die Klasse verwenden: ExpectedConditions um explizit darauf zu warten, dass ein Element auf der Webseite angezeigt wird, bevor Sie weitere Aktionen ausführen können

Mit der ExpectedConditionsKlasse können Sie feststellen, ob ein Element sichtbar ist:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

In der ExpectedConditions class JavadocListe finden Sie alle Bedingungen, die Sie überprüfen können.


10

Dies scheint eine ernsthafte Einschränkung von WebDriver zu sein. Das Warten auf ein Element bedeutet natürlich nicht, dass die Seite geladen wird. Insbesondere kann das DOM vollständig erstellt werden (Onready-Status), wobei JS noch ausgeführt wird und CSS und Bilder noch geladen werden.

Ich glaube, die einfachste Lösung besteht darin, eine JS-Variable für das Onload-Ereignis festzulegen, nachdem alles initialisiert wurde, und diese JS-Variable in Selen zu überprüfen und auf sie zu warten.


Es ist ganz einfach, wenn Sie die Website ändern möchten!
Reinierpost

Ja, verwenden Sie einfach einen JavascriptExecutor, um jQuery.js auszuführen, und dann haben Sie Zugriff auf jQuery-Ladeereignisse. Es ist jedoch ein seltener Fall, wenn dies notwendig ist. Der Standard-Webdriver verfügt über genügend Leistung, um 98% der richtigen Wartezeiten auszuführen.
Djangofan

@djangofan wäre großartig, ein Beispiel dafür zu sehen ... Ich bin ein Front-End-Typ, also nicht sicher, wo oder wie JavascriptExecutor verwendet wird.
BradGreens

@BradGreens - Ok, sieh dir mein Projekt hier an: github.com/djangofan/jquery-growl-selenium-example . Wenn Sie die Bandbreite haben, um dieses Beispiel zu beenden, konnte ich das jGrowl in diesem Testprojekt nicht ganz zum Laufen bringen, obwohl die jQuery einwandfrei funktioniert.
Djangofan

1
@BradGreens Zusätzlich zu Djangofans Kommentar finden Sie meine Antwort hier: stackoverflow.com/a/24638792/730326
jmathew

10

Imrans Antwort für Java 7 erneut aufbereitet:

    WebDriverWait wait = new WebDriverWait(driver, 30);

    wait.until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript(
                "return document.readyState"
            ).equals("complete");
        }
    });

9

Wenn Sie auf das Laden eines bestimmten Elements warten möchten, können Sie die isDisplayed()Methode für Folgendes verwenden RenderedWebElement:

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
    // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
    RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));

    // If results have been returned, the results are displayed in a drop down.
    if (resultsDiv.isDisplayed()) {
      break;
    }
}

(Beispiel aus dem 5-Minuten-Handbuch Erste Schritte )


4
Ein Jahr später (aktuelle Selenium-Version 2.23.1) gibt es keine RenderedWebElementin der API. Die isDisplayed()Methode ist jetzt jedoch direkt auf verfügbar WebElement.
Petr Janeček

1
Umfragen sind schrecklich, wenn sie vermieden werden können.
Reinierpost

8

Warten Sie explizit oder bedingt in dieser Wartezeit, bis diese Bedingung erfüllt ist.

WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));

Dies wartet 60 Sekunden lang auf jedes Webelement.

Verwenden Sie implizit das Warten auf jedes Element auf der Seite bis zu dieser bestimmten Zeit.

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

Dies wartet 60 Sekunden lang auf jedes Webelement.


5

Verwenden Sie implizit das Warten auf jedes Element auf der Seite bis zur angegebenen Zeit.

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

Warten Sie 30 Sekunden lang auf jedes Element auf der Seite.

Eine weitere Wartezeit ist Explizites Warten oder bedingtes Warten in dieser Wartezeit bis zur gegebenen Bedingung.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

Geben Sie in id die statische Element-ID an, die auf der Seite unterschiedlich angezeigt wird, sobald die Seite geladen wird.


4

Ich bin überrascht, dass Prädikate nicht die erste Wahl waren, da Sie normalerweise wissen, mit welchen Elementen Sie als Nächstes auf der Seite interagieren, auf die Sie warten. Mein Ansatz war es immer, Prädikate / Funktionen wie waitForElementByID(String id)und waitForElemetVisibleByClass(String className)usw. zu erstellen und diese dann zu verwenden und wiederzuverwenden, wo immer ich sie benötige, sei es zum Laden einer Seite oder zum Ändern des Seiteninhalts, auf den ich warte.

Beispielsweise,

In meiner Testklasse:

driverWait.until(textIsPresent("expectedText");

In meiner Testklasse Eltern:

protected Predicate<WebDriver> textIsPresent(String text){
    final String t = text;
    return new Predicate<WebDriver>(){
        public boolean apply(WebDriver driver){
            return isTextPresent(t);
        }
    };
}

protected boolean isTextPresent(String text){
    return driver.getPageSource().contains(text);
}

Obwohl dies viel zu sein scheint, müssen Sie wiederholt nachsehen, und das Intervall für die Überprüfungsdauer kann zusammen mit der endgültigen Wartezeit vor dem Timeout festgelegt werden. Außerdem werden Sie solche Methoden wiederverwenden.

In diesem Beispiel definiert die Elternklasse und initiiert das WebDriver driverund das WebDriverWait driverWait.

Ich hoffe das hilft.


Das hilft mir! Vielen Dank für dieses hervorragende Beispiel. Ich füge es meinem SeleniumHelper hinzu. vgl. javabox
boly38

4

Der beste Weg, um auf das Laden von Seiten zu warten, wenn Sie die Java-Bindungen für WebDriver verwenden, ist die Verwendung des Seitenobjekt-Entwurfsmusters mit PageFactory. Dies ermöglicht es Ihnen, die zu nutzenAjaxElementLocatorFactory was einfach ausgedrückt als globales Warten auf alle Ihre Elemente fungiert. Es gibt Einschränkungen für Elemente wie Dropboxen oder komplexe Javascript-Übergänge, aber es reduziert die benötigte Codemenge drastisch und beschleunigt die Testzeiten. Ein gutes Beispiel finden Sie in diesem Blogpost. Grundlegendes Verständnis von Core Java wird vorausgesetzt.

http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html


4

NodeJS-Lösung:

In Nodejs können Sie es über Versprechen bekommen ...

Wenn Sie diesen Code schreiben, können Sie sicher sein, dass die Seite vollständig geladen ist, wenn Sie zum ...

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

Wenn Sie diesen Code schreiben, navigieren Sie und Selen wartet 3 Sekunden ...

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...

Aus der Selendokumentation:

this.get (url) → Thenable

Plant einen Befehl zum Navigieren zur angegebenen URL.

Gibt ein Versprechen zurück, das aufgelöst wird, wenn das Dokument vollständig geladen wurde .

Selendokumentation (Nodejs)


4

Hier ist eine Java 8-Version der derzeit am besten bewerteten Antwort :

WebDriverWait wait = new WebDriverWait(myDriver, 15);
wait.until(webDriver -> ((JavascriptExecutor) myDriver).executeScript("return document.readyState").toString().equals("complete"));

Wo myDriverist ein WebDriverObjekt (früher deklariert).

Hinweis : Beachten Sie, dass diese Methode ( document.readyState) nur das DOM überprüft.


4

Rufen Sie unten Funktion in Ihrem Skript auf, dies wartet, bis die Seite nicht mit Javascript geladen wird

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}

Ich habe den Booleschen
Wert

3
/**
 * Call this method before an event that will change the page.
 */
private void beforePageLoad() {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("document.mpPageReloaded='notYet';");
}

/**
 * Call this method after an event that will change the page.
 * 
 * @see #beforePageLoad
 * 
 *      Waits for the previous page to disappear.
 */
private void afterPageLoad() throws Exception {
    (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Object obj = js.executeScript("return document.mpPageReloaded;");
            if (obj == null) {
                return true;
            }
            String str = (String) obj;
            if (!str.equals("notYet")) {
                return true;
            }
            return false;
        }
    });
}

Sie können vom Dokument zu einem Element wechseln, wenn nur ein Teil eines Dokuments geändert wird.

Diese Technik wurde von der Antwort von Sincebasic inspiriert.


3

SelenWaiter :

import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWaiter {

      private WebDriver driver;

      public SeleniumWaiter(WebDriver driver) {
           this.driver = driver;
      }

      public WebElement waitForMe(By locatorname, int timeout){
           WebDriverWait wait = new WebDriverWait(driver, timeout);
           return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
      }

      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
            // TODO Auto-generated method stub
            return new Function<WebDriver, WebElement>() {
                 @Override
                 public WebElement apply(WebDriver driver) {
                      return driver.findElement(locator);
                 }
            };
      }
 }

Und für Sie verwenden Sie es :

_waiter = new SeleniumWaiter(_driver);

try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}

3

Mit der folgenden vorhandenen Methode können Sie die Zeit für pageeLoadTimeout im folgenden Beispiel festlegen. Wenn das Laden der Seite länger als 20 Sekunden dauert, wird eine Ausnahme beim erneuten Laden der Seite ausgelöst

 WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)

2

Sie können explizit warten, bis ein Element auf der Webseite angezeigt wird, bevor Sie Maßnahmen ergreifen können (z. B. element.click ()).

driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
  .until(new ExpectedCondition<WebElement>(){
        @Override
        public WebElement apply(WebDriver d) {
        return d.findElement(By.id("myDynamicElement"));
}});

Dies ist, was ich für ein ähnliches Szenario verwendet habe und es funktioniert gut.


Ich denke, driver.get wartet, bis die Onload-Funktion beendet ist, bevor die Kontrolle über den Code zurückgegeben wird, es sei denn, die Seite enthält eine Menge Ajax
Goh

2

Mein einfacher Weg:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;

        while (System.currentTimeMillis() < end) {

            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }

2

Der beste Weg, den ich gesehen habe, ist die Nutzung der stalenessOf ExpectedCondition zu verwenden, um darauf zu warten, dass die alte Seite veraltet ist.

Beispiel:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);

WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));

Es wird zehn Sekunden warten, bis das alte HTML-Tag veraltet ist, und dann eine Ausnahme auslösen, wenn dies nicht der Fall ist.


1
Ein veraltetes WebElement bedeutet nicht, dass eine neue Seite geladen wird.
Corey Goldberg

Sicher, aber es bedeutet, dass die alte Seite vollständig entladen ist. Nach meiner Erfahrung ist es genauso wichtig zu wissen, wann die alte Seite entladen wurde oder ob sie aus irgendeinem Grund angehalten wurde.
Forresthopkinsa

Natürlich verwende ich normalerweise stalenessOf in Verbindung mit anderen Tests, um den vollständigen Entlade- / Ladeprozess zu erhalten.
Forresthopkinsa

2

Ich benutze Node + Selenium-Webdriver (welche Version ist jetzt 3.5.0). was ich dafür mache ist:

var webdriver = require('selenium-webdriver'),
    driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
  return state === 'complete';
}))

2

Sie können wait verwenden. Grundsätzlich gibt es zwei Arten von Wartezeiten in Selen

  • Implizites Warten
  • Explizites Warten

- Implizites Warten

Dies ist sehr einfach, siehe Syntax unten:

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

- Explizites Warten

Warten Sie explizit oder bedingt, bis eine bestimmte Bedingung erfüllt ist.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

Sie können wie andere Eigenschaften verwenden visblityOf(),visblityOfElement()



2

In meinem Fall habe ich Folgendes verwendet, um den Seitenladestatus zu ermitteln. In unserer Anwendung sind GIFs zum Laden vorhanden, und ich höre sie wie folgt an, um unerwünschte Wartezeiten im Skript zu vermeiden.

public static void processing(){ 
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}

Wo der xpath das GIF im HTML-DOM findet. Danach können Sie auch Ihre Aktionsmethoden implementieren. Klicken Sie auf.

public static void click(WebElement elementToBeClicked){
    WebDriverWait wait = new WebDriverWait(driver, 45);
    wait.until(ExpectedConditions.visibilityOf(element));
    wait.until(ExpectedConditions.elementToBeClickable(element)); 
    wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click(); 
 }

2

Mann all diese Antworten erfordern zu viel Code. Dies sollte eine einfache Sache sein, da es ziemlich häufig ist.

Warum nicht einfach ein einfaches Javascript mit dem Webdriver injizieren und überprüfen. Dies ist die Methode, die ich in meiner Webscraper-Klasse verwende. Das Javascript ist ziemlich einfach, auch wenn Sie js nicht kennen.

    def js_get_page_state(self):        
    """
    Javascript for getting document.readyState
    :return: Pages state.

    More Info: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
    """
    ready_state = self.driver.execute_script('return document.readyState')
    if ready_state == 'loading':
        self.logger.info("Loading Page...")
    elif ready_state == 'interactive':
        self.logger.info("Page is interactive")
    elif ready_state == 'complete':
        self.logger.info("The page is fully loaded!")
    return ready_state

1

Wie Selenium nach einem Klick auf das Laden der Seite wartet, bietet den folgenden interessanten Ansatz:

  1. Speichern Sie einen Verweis auf a WebElementvon der alten Seite.
  2. Klicken Sie auf den Link.
  3. Rufen Sie weiterhin Operationen auf, WebElementbis StaleElementReferenceExceptiondie Kasse ausgelöst wird.

Beispielcode:

WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
    try
    {
        link.isDisplayed();
        return false;
    }
    catch (StaleElementReferenceException unused)
    {
        return true;
    }
});

Gute Idee! Ich hätte nie gedacht, diese Situation zu lösen, indem ich das Gegenteil eines erfolgreichen Seitenladens, eines erfolgreichen Seitenentladens (mangels eines besseren Begriffs) überprüfe. Ob dies die beste Option ist, hängt jedoch davon ab, ob StaleElementReferenceException weniger Zeit usw. benötigt als das Warten auf ein erfolgreiches Laden. Trotzdem ein weiterer guter Weg, dies zu tun.
Joseph Orlando

4
Hier erfahren Sie nicht, ob die aktuelle Seite geladen ist, sondern ob die letzte Seite (insbesondere ein Element) entladen wurde . Sie müssen noch warten, bis die aktuelle Seite geladen ist. Übrigens können Sie Ihren obigen Code durch ersetzen new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(element)).
JeffC
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.