Ich arbeite an einem Java Selenium-WebDriver. Ich fügte hinzu
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
und
WebElement textbox = driver.findElement(By.id("textbox"));
weil das Laden der Benutzeroberfläche für meine Anwendungen einige Sekunden dauert. Also habe ich 2 Sekunden implizites Warten eingestellt. Ich konnte jedoch das Elementtextfeld nicht finden
Dann füge ich hinzu Thread.sleep(2000);
Jetzt funktioniert es gut. Welcher ist ein besserer Weg?
Antworten:
Nun, es gibt zwei Arten von Wartezeiten: explizite und implizite Wartezeiten. Die Idee des expliziten Wartens ist
Das Konzept des impliziten Wartens ist
Details können Sie hier erfahren .
In solchen Situationen würde ich es vorziehen, explizit zu warten (
fluentWait
insbesondere):fluentWait
Funktion gibt Ihr gefundenes Webelement zurück. Aus der Dokumentation zufluentWait
: Eine Implementierung der Wait-Schnittstelle, deren Zeitlimit und Abfrageintervall möglicherweise im laufenden Betrieb konfiguriert sind. Jede FluentWait-Instanz definiert die maximale Wartezeit auf eine Bedingung sowie die Häufigkeit, mit der die Bedingung überprüft wird. Darüber hinaus kann der Benutzer das Warten so konfigurieren, dass bestimmte Arten von Ausnahmen während des Wartens ignoriert werden, z. B. NoSuchElementExceptions, wenn nach einem Element auf der Seite gesucht wird. Details erhalten Sie hierVerwendung
fluentWait
in Ihrem Fall wie folgt sein:Dieser Ansatz ist meiner Meinung nach besser, da Sie nicht genau wissen, wie viel Zeit Sie warten müssen, und Sie im Abfrageintervall einen beliebigen Zeitwert festlegen können, durch den das Vorhandensein von Elementen überprüft wird. Grüße.
quelle
import com.google.common.base.Function;
nichtimport java.util.function.Function;
Function
verwendet werden. Das war mir zunächst nicht klar. Danke für die Antwort.driver -> driver.findElement(locator)
. Wenn Sie dies verwenden, benötigen Sie überhaupt keine Importanweisung..withTimeout(Duration.ofSeconds(30)).pollingEvery(Duration.ofSeconds(5))
anstelle von:.withTimeout(30, TimeUnit.SECONDS).pollingEvery(5, TimeUnit.SECONDS)
Dieser Thread ist etwas älter, dachte aber, ich würde posten, was ich gerade mache (in Arbeit).
Obwohl ich immer noch auf Situationen stoße, in denen das System stark ausgelastet ist und wenn ich auf eine Senden-Schaltfläche (z. B. login.jsp) klicke, kehren alle drei Bedingungen (siehe unten) zurück,
true
aber die nächste Seite (z. B. home.jsp) ist nicht vorhanden. Ich habe noch nicht mit dem Laden begonnen.Dies ist eine generische Wartemethode, die eine Liste von ExpectedConditions erstellt.
Ich habe verschiedene wiederverwendbare ExpectedConditions definiert (drei davon sind unten aufgeführt). In diesem Beispiel umfassen die drei erwarteten Bedingungen document.readyState = 'complete', kein "wait_dialog" und keine 'spinners' (Elemente, die angeben, dass asynchrone Daten angefordert werden).
Nur die erste kann generisch auf alle Webseiten angewendet werden.
Abhängig von der Seite kann ich eine oder alle verwenden:
Es gibt auch vordefinierte ExpectedConditions in der folgenden Klasse: org.openqa.selenium.support.ui.ExpectedConditions
quelle
Wenn Sie webdriverJs (node.js) verwenden,
Der obige Code lässt den Browser nach dem Klicken auf die Schaltfläche 5 Sekunden warten.
quelle
Die Verwendung
Thread.sleep(2000);
ist ein bedingungsloses Warten. Wenn Ihr Test schneller geladen wird, müssen Sie noch warten. Also im Prinzip mitimplicitlyWait
ist also die bessere Lösung.Ich verstehe jedoch nicht, warum
implicitlyWait
dies in Ihrem Fall nicht funktioniert. Haben Sie gemessen, ob dasfindElement
tatsächlich zwei Sekunden dauert, bevor eine Ausnahme ausgelöst wird? Wenn ja, können Sie versuchen, die bedingte Wartezeit von WebDriver wie in dieser Antwort beschrieben zu verwenden?quelle
Ich verwende gerne benutzerdefinierte Bedingungen. Hier ist ein Code in Python:
Wann immer Sie warten müssen, können Sie dies explizit tun, indem Sie die Existenz eines bestimmten Elements überprüfen (dieses Element kann von Seite zu Seite variieren).
find_elements_by_id
Rückgabeliste - leer oder nicht, Sie müssen nur überprüfen.quelle
Klick scheint zu blockieren? - Hier ist eine andere Möglichkeit zu warten, wenn Sie WebDriverJS verwenden:
Der obige Code wartet, nachdem auf die Schaltfläche geklickt wurde, bis die nächste Seite geladen ist, und greift dann auf die Quelle der nächsten Seite zu.
quelle
Implizit warten und Thread.sleep Beide werden nur für die Synchronisation verwendet. Der Unterschied besteht jedoch darin, dass wir implizit auf das gesamte Programm warten können, Thread.sleep jedoch nur für diesen einzelnen Code funktioniert. Hier ist mein Vorschlag, implizit einmal im Programm warten Wenn Ihre Webseite jedes Mal aktualisiert wird, verwenden Sie Thread.sleep zu diesem Zeitpunkt. Es wird viel besser :)
Hier ist mein Code:
quelle
Manchmal scheint das implizite Warten überschrieben zu werden und die Wartezeit wird verkürzt. [@ eugene.polschikov] hatte eine gute Dokumentation über das Warum. Ich habe in meinen Tests und Codierungen mit Selenium 2 festgestellt, dass implizite Wartezeiten gut sind, aber gelegentlich müssen Sie explizit warten.
Es ist besser zu vermeiden, direkt einen Thread zum Schlafen zu rufen, aber manchmal gibt es keinen guten Weg, um ihn zu umgehen. Es gibt jedoch andere von Selen bereitgestellte Warteoptionen, die helfen. waitForPageToLoad und waitForFrameToLoad haben sich als besonders nützlich erwiesen.
quelle
Implizites Warten: Während des impliziten Wartens wartet der WebDriver auf die angegebene Zeit und versucht nicht, das Element während des angegebenen Zeitraums erneut zu finden, wenn der Webtreiber es aufgrund seiner Verfügbarkeit nicht sofort finden kann. Sobald die angegebene Zeit abgelaufen ist, wird versucht, das Element das letzte Mal erneut zu durchsuchen, bevor eine Ausnahme ausgelöst wird. Die Standardeinstellung ist Null. Sobald wir eine Zeit festgelegt haben, wartet der Web-Treiber auf den Zeitraum der WebDriver-Objektinstanz.
Explizites Warten: Es kann vorkommen, dass das Laden eines bestimmten Elements länger als eine Minute dauert. In diesem Fall möchten Sie definitiv keine große Zeit für implizites Warten festlegen. Wenn Sie dies tun, wartet Ihr Browser für jedes Element zur gleichen Zeit. Um diese Situation zu vermeiden, können Sie einfach nur für das erforderliche Element eine separate Zeit festlegen. Wenn Sie dies befolgen, ist die implizite Wartezeit Ihres Browsers für jedes Element kurz und für ein bestimmtes Element groß.
quelle
Manchmal schlägt implizites Warten fehl und sagt, dass ein Element existiert, aber es existiert wirklich nicht.
Die Lösung besteht darin, die Verwendung von driver.findElement zu vermeiden und es durch eine benutzerdefinierte Methode zu ersetzen, die implizit eine explizite Wartezeit verwendet. Beispielsweise:
Es gibt weitere Gründe, um implizites Warten zu vermeiden, außer sporadischen, gelegentlichen Fehlern (siehe diesen Link ).
Sie können diese "Element" -Methode genauso wie driver.findElement verwenden. Beispielsweise:
Wenn Sie wirklich nur ein paar Sekunden auf die Fehlerbehebung oder eine andere seltene Gelegenheit warten möchten, können Sie eine Pausenmethode erstellen, die der von Selenium IDE ähnelt:
quelle
Antwort : Warten Sie einige Sekunden, bevor die Sichtbarkeit der Elemente mit Selenium WebDriver die folgenden Methoden durchläuft.
implicitlyWait () : Die WebDriver-Instanz wartet bis zum vollständigen Laden der Seite. Sie müssen 30 bis 60 Sekunden verwenden, um das Laden der gesamten Seite abzuwarten.
ExplicitlyWait WebDriverWait () : Die WebDriver-Instanz wartet bis zum vollständigen Laden der Seite.
Hinweis : Verwenden Sie ExplicitlyWait WebDriverWait (), um ein bestimmtes WebElement zu verarbeiten.
quelle
Aktionen verwenden -
Siehe Aktion # Pause- Methode.
quelle
Ich bevorzuge den folgenden Code, um 2 Sekunden zu warten.
quelle
ist das Schlimmste: Da es sich um ein statisches Warten handelt, wird das Testskript langsamer.
Dies ist ein dynamisches Warten
Schließlich schlage ich vor
mit einigen vordefinierten Bedingungen:
quelle
Dies hat mir geholfen, aber die InterruptedException-Ausnahme muss behoben werden. Umgib es also besser mit try and catch:
ODER
Wurferklärung hinzufügen:
Ich würde den zweiten vorziehen, da man ihn dann
sleep()
so oft verwenden kann, wie er möchte, und die Wiederholungtry
undcatch
Blockierung jedes Mal vermeiden kann, wennsleep()
er verwendet wurde.quelle