it-swarm.com.de

Wann wird explizites Warten im Vergleich zum impliziten Warten in Selenium Webdriver verwendet?

Ich benutze:

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

Für das unten stehende Element fällt es jedoch immer wieder aus 

    driver.findElement(By.id("name")).clear();
    driver.findElement(By.id("name")).sendKeys("Create_title_01");

Ich habe einen Wartecode hinzugefügt:

for (int second = 0;; second++) {
        if (second >= 120) fail("timeout");
        try { if (isElementPresent(By.id("name"))) break; } catch (Exception e) {}
        Thread.sleep(1000);
    }

Sollte implizites Warten nicht darauf warten, bis ein Element gefunden wird? Wäre es auch besser, wenn ich explizites Warten anstelle des Codes benutze, den ich hinzugefügt habe und Thread.sleep() hat?

37
SUM

TL; DR: Verwenden Sie immer explizites Warten. Vergiss das implizite Warten.


Hier ist ein kurzer Überblick über die Unterschiede zwischen explizitem und implizitem Warten:

Explizites Warten:

  • dokumentiertes und definiertes Verhalten.
  • läuft im lokalen Teil von Selenium (in der Sprache Ihres Codes).
  • funktioniert unter allen erdenklichen bedingungen.
  • gibt entweder Erfolg oder Timeout-Fehler zurück.
  • kann das Fehlen eines Elements als Erfolgsbedingung definieren.
  • kann die Verzögerung zwischen Wiederholungen und zu ignorierenden Ausnahmen anpassen.

Implizites Warten:

  • undokumentiertes und praktisch undefiniertes Verhalten.
  • läuft im entfernten Teil von Selenium (dem Teil, der den Browser steuert).
  • funktioniert nur bei find Elementmethoden.
  • liefert entweder ein Element gefunden oder (nach dem Timeout) nicht gefunden.
  • wenn auf Abwesenheit geprüft wird, muss immer bis zum Timeout gewartet werden.
  • kann nicht anders als globales Timeout angepasst werden.

Sehen wir uns den Unterschied zwischen expliziter Wartezeit und impliziter Wartezeit im eigentlichen Quellcode von Selenium an. Ich habe den Code aus der Python-Bindung von Selenium kopiert, da Python "einfach zu lesen" ist.

Der Code von WebDriverWait.until() (explizites Warten):

def until(self, method, message=''):
    end_time = time.time() + self._timeout
    while(True):
        try:
            value = method(self._driver)
            if value:
                return value
        except self._ignored_exceptions:
            pass
        time.sleep(self._poll)
        if(time.time() > end_time):
            break
    raise TimeoutException(message)

Jetzt in menschlicher Sprache: explizite Wartezeit erwartet eine Methode, die bei Erfolg einen echten Wert zurückgibt. Sie führt dann die angegebene Methode wiederholt mit einer Verzögerung dazwischen aus. Erwartete Fehler der angegebenen Methode werden unterdrückt. Wenn die angegebene Methode einen echten Wert zurückgibt, gibt der explizite Warten diesen Wert zurück. Wenn die Zeit abgelaufen ist, wird eine Timeout-Ausnahme ausgelöst.

Vergleiche den Code von WebDriver.implicitly_wait() (Kommentare wurden aus Gründen der Kürze entfernt):

def implicitly_wait(self, time_to_wait):
    self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000})

self.execute() ist WebDriver.execute() , die RemoteConnection.execute() aufruft, was wiederum, soweit ich das beurteilen kann, einen RPC an die Remote-Seite von Selenium sendet.

In menschlicher Sprache: Das implizite Warten sendet eine Nachricht an die "entfernte Seite" des Selenium-Web-Treibers. Die Remote-Seite des Selenium-Treibers ist der Teil von Selenium, der den Browser tatsächlich steuert. Was macht die Gegenstelle mit der Nachricht? "Es hängt davon ab, ob". Dies hängt vom Betriebssystem und vom Browser sowie von der Version von Selenium ab. Soweit ich das beurteilen kann, gibt es keine Garantie für das tatsächliche Verhalten einer bestimmten Implementierung.

Mögliche Implementierungen sind:

  • versuchen Sie wiederholt, das Element bis zum Timeout zu finden. Rückkehr sobald Element gefunden wird.
  • versuchen Sie, ein Element zu finden. Warte bis zum Timeout. versuchen Sie es nochmal.
  • warte bis zum Timeout. Versuchen Sie, ein Element zu finden.

Beachten Sie, dass das implizite Warten nur für die Methoden von find element (s) gilt.

Ich habe den eigentlichen Quellcode der entfernten Seiten von Selenium nicht nachgeschlagen. Die Informationen werden durch Lesen der Kommentare in dem Fehlerbericht über implizites und explizites Warten in Selenium gesammelt:

Meine Schlussfolgerung: Das implizite Warten ist schlecht. Die Fähigkeiten sind begrenzt. Das Verhalten ist undokumentiert und von der Implementierung abhängig.

Explizites Warten kann alles implizite Warten und mehr. Der einzige Nachteil des expliziten Wartens ist etwas mehr Aufwand aufgrund mehrerer Remoteprozeduraufrufe. Auch das explizite Warten ist etwas ausführlicher. Diese Ausführlichkeit macht den Code jedoch explizit. Und explizit ist besser als implizit. Recht?


Lesen Sie weiter:

80
lesmana

Implizites Warten - Es ist globale Einstellung für alle Elemente anwendbar. Wenn das Element vor dem angegebenen Zeitpunkt erscheint, beginnt das Skript, andernfalls führt das Skript NoSuchElementException aus. Beste Möglichkeit, in Setup-Methode zu verwenden. Betrifft nur By.findelement().

Thread.sleep() - Es wird Zeit für das Skript schlafen, kein guter Weg , um es in Skript zu verwenden, da es ohne Bedingung im Ruhezustand ist. Was ist, wenn 2 Sekunden in 5% der Fälle nicht ausreichen?

Explizites Warten : Warten auf Angabe enthält/Attributänderung. Wird häufiger verwendet, wenn die AnwendungAJAXan das System anruft und dynamische Daten und das Rendern auf der Benutzeroberfläche abruft. In diesem Fall ist WebDriverWait geeignet.

4
Anand Somani

Haben Sie FluentWait ausprobiert? Eine Implementierung der Wait-Schnittstelle, deren Zeitlimit und Abrufintervall möglicherweise sofort konfiguriert werden. Jede FluentWait-Instanz definiert die maximale Wartezeit für eine Bedingung sowie die Häufigkeit mit dem der Zustand überprüft werden soll. Darüber hinaus kann der Benutzer das Warten so konfigurieren, dass bestimmte Arten von Ausnahmen während des Wartens ignoriert werden, z. B. NoSuchElementExceptions bei der Suche nach einem Element auf der Seite.

siehe diesen Link fließend warten Beschreibung

Insbesondere habe ich auf diese Weise fließend gewartet:

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;              }     ;

Wie Sie bemerkt haben, wird beim fließenden Warten das gefundene Webelement zurückgegeben. Sie übergeben also den Locator einfach mit dem By-Typ und können dann alle Aktionen für das gefundene Webelement ausführen.

fluentWait(By.id("name")).clear();

Hoffe das hilft dir)

4

Haben Sie versucht, ' WebDriverWait ' zu verwenden? Ich stelle mir vor, Sie möchten folgendes:

WebDriverWait _wait = new WebDriverWait(driver, new TimeSpan(0, 0, 2)); //waits 2 secs max
_wait.Until(d => d.FindElement(By.Id("name")));
//do your business on the element here :)

Nach meinem Verständnis wird dies so ziemlich der aktuelle Code sein. Es wird die Methode ständig versuchen (wobei die nicht gefundenen Ausnahmen ignoriert werden), bis das Zeitlimit der verstrichenen Zeitspanne erreicht ist und ein dritter Parameter eingegeben werden kann, um den Schlaf in Millisekunden anzugeben. Tut mir leid, wenn dies auch implizit funktioniert:

Edit: Ich habe heute etwas gelesen und verstehe Ihre Frage besser und erkenne, dass dies genau das tut, was Ihre Einstellung des impliziten Wartens tun sollte. Lässt es hier nur für den Fall, dass der Code selbst jemandem helfen kann.

2
Nashibukasan

ImplicitWait:

    1. Static Wait 
    2. UnConditional Wait. ( No Conditions were given)
    3. Applicable throughout the program

Das implizite Warten in Java - Selenium deklarieren:

driver.manage().timeout().implicitWait(20, TimeUnit.Seconds());

Explizites Warten:

  1. Dynamisches Warten
  2. Bedingtes Warten.
  3. Gilt nicht für das gesamte Programm 

Das explizite Warten in Java Selenium deklarieren.

WebDriverWait wait=new WebDriverWait(driver, 20); wait.until(somecondition);
1
Kiran Sk

Implizite Wartezeiten werden verwendet, um eine Wartezeit (z. B. 30 Sekunden) zwischen den aufeinanderfolgenden Testschritten über das gesamte Testskript oder -programm hinweg bereitzustellen. Der nächste Schritt wird nur ausgeführt, wenn die 30 Sekunden (oder die angegebene Zeit abgelaufen ist) nach der Ausführung des vorherigen Schritts ausgeführt wird

Syntax:  

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

Explizite Wartezeiten werden verwendet, um die Ausführung anzuhalten, bis der Zeitpunkt erreicht ist, zu dem eine bestimmte Bedingung erfüllt ist oder die festgelegte maximale Zeit abgelaufen ist. Das implizite Warten wurde zwischen den einzelnen aufeinander folgenden Testschritten für das gesamte Testskript oder die gesamten Programme angewendet, während Explicit-Warten nur für eine bestimmte Instanz angewendet wird.

Syntax:  

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver,30);
0
iamsankalp89