@Michael Freidgeim: Bevor Sie jemanden beschuldigen, eine doppelte Frage geschrieben zu haben, überprüfen Sie bitte das Erstellungsdatum der Frage, um zu entscheiden, welches das Duplikat ist.
Dies ist mein Ansatz: if(driver.findElements().Count() > 0)
– Ali CAKIL
12. April um 9:48 Uhr
Edd
Ich stimme Mikes Antwort zu, aber es gibt eine implizite Wartezeit von 3 Sekunden, wenn keine Elemente gefunden werden, die ein-/ausgeschaltet werden können, was nützlich ist, wenn Sie diese Aktion häufig ausführen:
Wenn Sie dies in eine Hilfsmethode einfügen, sollte die Leistung verbessert werden, wenn Sie viele Tests ausführen.
Da der implizite Timeout 3 Sekunden, aber auch ein anderer Wert sein kann, sollte man den alten Wert erst speichern und dann evtl. zurücksetzen. Aber leider kann man den Wert setzen, aber nicht lesen — coole API
– Ralf
9. Januar 2012 um 15:02 Uhr
Es scheint, dass die standardmäßige implizite Wartezeit 0 ist, (seleniumhq.org/docs/04_webdriver_advanced.html) Wenn Sie es also nicht länger konfiguriert haben, sollte dies nicht erforderlich sein.
– Andreas M
24. Mai 2012 um 9:43 Uhr
@Ralph gibt es eine Möglichkeit, den aktuellen Wert zu erhalten?
– Tim Büthe
20. September 2012 um 16:19 Uhr
Zuerst stellt man es irgendwo auf, man sollte es selbst verstauen. Der Standardwert ist ebenfalls angegeben.
– szab.kel
24. Oktober 2014 um 22:16 Uhr
Brantley Blanchard
Wie im Kommentar angegeben, ist dies in C # nicht Java, aber die Idee ist dieselbe. Ich habe dieses Problem ausgiebig untersucht und letztendlich ist das Problem, dass FindElement immer eine Ausnahme zurückgibt, wenn das Element nicht vorhanden ist. Es gibt keine überladene Option, mit der Sie null oder irgendetwas anderes erhalten können. Deshalb bevorzuge ich diese Lösung gegenüber anderen.
Das Zurückgeben einer Liste von Elementen und das anschließende Überprüfen, ob die Listengröße 0 ist, funktioniert, aber Sie verlieren auf diese Weise die Funktionalität. Sie können kein .click() auf eine Sammlung von Links anwenden, selbst wenn die Sammlungsgröße 1 ist.
Sie könnten behaupten, dass das Element existiert, aber das stoppt oft Ihre Tests. In einigen Fällen muss ich auf einen zusätzlichen Link klicken, je nachdem, wie ich zu dieser Seite gelangt bin, und ich möchte darauf klicken, falls vorhanden, oder anderweitig fortfahren.
Es ist nur langsam, wenn Sie das Timeout nicht festlegen driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
Es ist eigentlich sehr einfach und elegant, sobald die Methode erstellt wurde. Durch die Nutzung FindElementSafe Anstatt von FindElementich “sehe” den hässlichen Try/Catch-Block nicht und kann einen einfachen verwenden Existiert Methode. Das würde in etwa so aussehen:
IWebElement myLink = driver.FindElementSafe(By.Id("myId"));
if (myLink.Exists)
{
myLink.Click();
}
So erweitern Sie IWebElement & IWebDriver
IWebDriver.FindElementSafe
/// <summary>
/// Same as FindElement only returns null when not found instead of an exception.
/// </summary>
/// <param name="driver">current browser instance</param>
/// <param name="by">The search string for finding element</param>
/// <returns>Returns element or null if not found</returns>
public static IWebElement FindElementSafe(this IWebDriver driver, By by)
{
try
{
return driver.FindElement(by);
}
catch (NoSuchElementException)
{
return null;
}
}
IWebElement.Existiert
/// <summary>
/// Requires finding element by FindElementSafe(By).
/// Returns T/F depending on if element is defined or null.
/// </summary>
/// <param name="element">Current element</param>
/// <returns>Returns T/F depending on if element is defined or null.</returns>
public static bool Exists(this IWebElement element)
{
if (element == null)
{ return false; }
return true;
}
Sie könnten Polymorphismus verwenden, um die IWebDriver-Klasseninstanz von FindElement zu ändern, aber das ist aus Wartungssicht eine schlechte Idee.
Es gibt zwei Probleme: 1) falsche Sprache: Java nicht C#, 2) Sie haben den hässlichen Try/Catch-Workaround verwendet (und das war die Frage, ob es einen anderen Weg als diesen hässlichen und langsamen Try/Catch gibt)
– Ralf
5. August 2013 um 15:34 Uhr
Ja, das ist C#, aber das Konzept ist dasselbe. Try/Catch ist nur hässlich, wenn man es oft machen muss. Deshalb habe ich es in einer separaten Methode gekapselt. Die endgültige Lösung ist eigentlich sehr hübsch. bool existiert = Treiber.FindElementSafe(by).Exists();
– Brantley Blanchard
5. August 2013 um 20:07 Uhr
Try/Catch ist nicht nur hässlich im Code, sondern langsam zur Laufzeit. Es in einer anderen Methode zu kapseln, behandelt das erste Problem, aber nicht das zweite.
– Vince Bowdren
14. April 2015 um 16:01 Uhr
lol, UI-Tests sind nicht für Geschwindigkeit bekannt, daher ist es die Spitze der “Agile Testing Pyramid”. Der Bruchteil einer Sekunde, der bei einer Try/Catch-ID verloren geht, wird durch die Zeit in den Schatten gestellt, die zum Abrufen und Rendern einer Seite in Chrome oder einem anderen von Ihnen verwendeten Browser benötigt wird. Wenn Sie sich solche Sorgen um Sekundenbruchteile machen, führen Sie die falsche Art von Tests durch. Ich würde vorschlagen, in diesem Fall mehr Unit-Tests durchzuführen.
– Brantley Blanchard
15. April 2015 um 15:47 Uhr
Amstel-Bytes
Das funktioniert bei mir jedes Mal:
if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
// Then click on the submit button
}else{
// Do something else as submit button is not there
}
Lotzi
Ich habe die Implementierung von Selenium WebDriver erweitert, in meinem Fall HtmlUnitDriver, um eine Methode verfügbar zu machen.
public boolean isElementPresent(By by){}
so was:
Überprüfen Sie, ob die Seite innerhalb eines Timeout-Zeitraums geladen wird.
Sobald die Seite geladen ist, senke ich die implizite Wartezeit des WebDrivers auf einige Millisekunden, in meinem Fall 100 Millisekunden, aber es sollte wahrscheinlich auch mit 0 Millisekunden funktionieren.
Rufen Sie findElements(By) auf. Der WebDriver wartet, auch wenn er das Element nicht findet, nur die Zeit von oben.
Erhöhen Sie die implizite Wartezeit für das zukünftige Laden der Seite
Hier ist mein Code:
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
public class CustomHtmlUnitDriver extends HtmlUnitDriver {
public static final long DEFAULT_TIMEOUT_SECONDS = 30;
private long timeout = DEFAULT_TIMEOUT_SECONDS;
public long getTimeout() {
return timeout;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public boolean isElementPresent(By by) {
boolean isPresent = true;
waitForLoad();
// Search for elements and check if list is empty
if (this.findElements(by).isEmpty()) {
isPresent = false;
}
// Rise back implicitly wait time
this.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
return isPresent;
}
public void waitForLoad() {
ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver wd) {
// This will tel if page is loaded
return "complete".equals(((JavascriptExecutor) wd).executeScript("return document.readyState"));
}
};
WebDriverWait wait = new WebDriverWait(this, timeout);
// Wait for page complete
wait.until(pageLoadCondition);
// Lower implicitly wait time
this.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
}
}
Verwendung:
CustomHtmlUnitDriver wd = new CustomHtmlUnitDriver();
wd.get("http://example.org");
if (wd.isElementPresent(By.id("Accept"))) {
wd.findElement(By.id("Accept")).click();
}
else {
System.out.println("Accept button not found on page");
}
@Michael Freidgeim: Bevor Sie jemanden beschuldigen, eine doppelte Frage geschrieben zu haben, überprüfen Sie bitte das Erstellungsdatum der Frage, um zu entscheiden, welches das Duplikat ist.
– Ralf
29. April 2016 um 7:36 Uhr
Ich mache dir keine Vorwürfe. Es ist nur eine Art Haushaltsführung, ähnliche Fragen miteinander zu verknüpfen. Siehe Soll ich dafür stimmen, eine doppelte Frage zu schließen, obwohl sie viel neuer ist und aktuellere Antworten enthält? “Wenn die neue Frage eine bessere Frage ist oder bessere Antworten hat, dann stimmen Sie dafür, die alte als Duplikat der neuen zu schließen.”
– Michael Freigeim
29. April 2016 um 13:26 Uhr