Testen Sie mit Selenium WebDriver, ob ein Element vorhanden ist.

163

Gibt es eine Möglichkeit zu testen, ob ein Element vorhanden ist? Jede findElement-Methode würde mit einer Ausnahme enden, aber das ist nicht das, was ich möchte, da es sein kann, dass ein Element nicht vorhanden ist und das in Ordnung ist, dass der Test nicht fehlschlägt, sodass eine Ausnahme nicht die Lösung sein kann.

Ich habe diesen Beitrag gefunden: Selenium c # Webdriver: Warten Sie, bis das Element vorhanden ist. Dies ist jedoch für C # und ich bin nicht sehr gut darin. Kann jemand den Code in Java übersetzen? Es tut mir leid, Leute, ich habe es in Eclipse ausprobiert, aber ich verstehe es nicht richtig in Java-Code.

Dies ist der Code:

public static class WebDriverExtensions{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds){

        if (timeoutInSeconds > 0){
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }

        return driver.FindElement(by);
    }
}
Prüfer
quelle
Ich habe einige Methoden, die sehr effektiv bei der Suche nach einem Objekt funktionieren, aber es hängt davon ab, was Sie damit machen möchten. Möchten Sie beispielsweise nach dem Element suchen, bis es existiert, möchten Sie danach suchen, bis es nicht mehr existiert, oder möchten Sie nur versuchen, es zu finden?
CBRRacer
1
Java ist C # sehr ähnlich. Ich denke, eines der Hauptprobleme, auf das Sie hier stoßen, ist Java. Es ist WebElement anstelle von IWebElement
CBRRacer
Kennen Sie die implizite Wartemethode? Wenn Sie dies zu Beginn des Tests einrichten, müssen Sie nie nach der Existenz eines Elements suchen, da es den impliziten Wartewert zum Abrufen verwendet. Wenn dieser Wert jedoch überschritten wird, wird eine Ausnahme
Bob Evans
Hier ist mein Beitrag über WebDriverWait in Java: WebDriverWait
Wenn einer der beiden Fälle in Ordnung ist, kann dies für die Testleistung problematisch sein, da sich die Wartezeit für das Warten auf ein Element, von dem Sie nicht erwarten, dass es existiert, tatsächlich summiert. Ich habe ein paar Hacks verwendet, um die Wartezeit zu umgehen, habe aber noch keine wirklich saubere Lösung dafür gefunden.
Mrfreester

Antworten:

277

Verwenden Sie findElementsanstelle von findElement.

findElements gibt eine leere Liste zurück, wenn anstelle einer Ausnahme keine übereinstimmenden Elemente gefunden werden.

Um zu überprüfen, ob ein Element vorhanden ist, können Sie dies versuchen

Boolean isPresent = driver.findElements(By.yourLocator).size() > 0

Dies gibt true zurück, wenn mindestens ein Element gefunden wurde, und false, wenn es nicht vorhanden ist.

Die offizielle Dokumentation empfiehlt diese Methode:

findElement sollte nicht verwendet werden, um nach nicht vorhandenen Elementen zu suchen, findElements (By) zu verwenden und stattdessen eine Antwort mit der Länge Null zu aktivieren.

el roso
quelle
32
Dies wird viel Zeit in Anspruch nehmen, um Ihre Tests auszuführen. Sie können diese Technik nicht überall anwenden.
Droogans
8
@Droogans - Ich werde Ihren Tests keine Zeit hinzufügen. Der Grund dafür ist, dass die implizite Standardwartezeit immer noch 0 ist. Wenn Sie die implizite Standardwartezeit erhöht haben, stimme ich dem zu, aber dies scheint hier nicht der Fall zu sein.
Djangofan
1
Guter Anruf Djangofan! Ich habe diese Strategie erfolgreich angewendet, indem ich die implizite Wartezeit des Treiber-Timeouts auf Null geändert und dann wieder auf den vorherigen Wert zurückgesetzt habe.
Schmirgel
3
Dies führte zu einer NoSuchElementFound-Ausnahme, was eine Schande ist, da ich gehofft hatte, diese zu verwenden, um zu vermeiden, dass diese Ausnahme in einer bestimmten Instanz abgefangen wird.
1
Viel einfacher ist die Verwendung von: if (driver.getPageSource (). Enthält ("Ein Text in Seite")) {} Wenn die Seite diesen Text enthält, ist die Bedingung wahr, oder sie ist falsch und Sie können codieren entsprechend.
Pradyot
56

Was ist mit einer privaten Methode, die einfach nach dem Element sucht und feststellt, ob es so vorhanden ist:

private boolean existsElement(String id) {
    try {
        driver.findElement(By.id(id));
    } catch (NoSuchElementException e) {
        return false;
    }
    return true;
}

Das wäre ganz einfach und macht den Job.

Bearbeiten: Sie können sogar noch weiter gehen und einen By elementLocatoras-Parameter verwenden, um Probleme zu vermeiden, wenn Sie das Element anhand einer anderen ID als id suchen möchten.

Dennis
quelle
3
Ja, das ist der richtige Weg. Verstehe nicht, warum Leute diesen Weg ignorieren und übereinstimmende Elemente zählen, um zu sehen, ob das Ergebnis 0 ist.
Ralph Lavelle
45
Nun, ich muss sagen, dass die Verwendung von Ausnahmen zur Regulierung des Programmflusses nicht der beste Weg ist.
Dennis
2
Huh? Es war dein Vorschlag! Es ist ein guter Weg, wenn Ihr Test erwartet, das Element nicht zu finden. Wie Sie zeigen, geben Sie einfach null zurück und assert.isnull oder isnotnull. Dies ist eine sinnvolle Methode, um zu testen, ob etwas vorhanden ist.
Ralph Lavelle
2
Falls ich die Frage "Gibt es eine Möglichkeit, zu testen, ob ein Element vorhanden ist?" Falsch interpretiert habe. falsch, ich werde froh sein zu erfahren, warum Ihre Meinung darüber unterschiedlich ist, ob dies eine legitime Antwort ist oder nicht.
Dennis
Möglicherweise möchten Sie die Wartezeit verkürzen. Im Moment, wenn das Element nicht existiert, müssen Sie "30 Sekunden" warten, bevor die Funktion false zurückgibt
Jason Smiley
14

Ich fand, dass dies für Java funktioniert:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);
Tango Ben
quelle
18
presenceOfElementLocatedlöst eine Ausnahme aus, wenn das Element bei einem bestimmten Versuch nicht gefunden wird. Um dies zu vermeiden, fügen Sie wait.ignoring(NoSuchElementException.class);zwischen der ersten und der zweiten Zeile eine Anweisung hinzu.
Steve Chambers
8
public static WebElement FindElement(WebDriver driver, By by, int timeoutInSeconds)
{
    WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
    wait.until( ExpectedConditions.presenceOfElementLocated(by) ); //throws a timeout exception if element not present after waiting <timeoutInSeconds> seconds
    return driver.findElement(by);
}
RedDeckWins
quelle
5

Ich hatte das gleiche Problem. Abhängig von der Berechtigungsstufe eines Benutzers werden einige Links, Schaltflächen und andere Elemente für mich nicht auf der Seite angezeigt. Ein Teil meiner Suite war das Testen, dass die Elemente, die fehlen sollten, fehlen. Ich habe stundenlang versucht, das herauszufinden. Ich habe endlich die perfekte Lösung gefunden.

Dies weist den Browser an, nach allen angegebenen Elementen zu suchen. Wenn dies zu einem Ergebnis 0führt, wurden keine Elemente gefunden, die auf der Spezifikation basieren. Dann lasse ich den Code eine if-Anweisung ausführen, um mich wissen zu lassen, dass sie nicht gefunden wurde.

C#Da dies der Fall ist , müssten Übersetzungen vorgenommen werden Java. Sollte aber nicht zu schwer sein.

public void verifyPermission(string link)
{
    IList<IWebElement> adminPermissions = driver.FindElements(By.CssSelector(link));
    if (adminPermissions.Count == 0)
    {
        Console.WriteLine("User's permission properly hidden");
    }
}

Es gibt auch einen anderen Weg, den Sie einschlagen können, je nachdem, was Sie für Ihren Test benötigen.

Das folgende Snippet überprüft, ob auf der Seite ein ganz bestimmtes Element vorhanden ist. Abhängig von der Existenz des Elements lasse ich den Test ein if else ausführen.

Wenn das Element vorhanden ist und auf der Seite angezeigt wird, habe ich es console.writemir mitgeteilt und gehe weiter. Wenn das betreffende Element vorhanden ist, kann ich den benötigten Test nicht ausführen. Dies ist der Hauptgrund für die Einrichtung.

Wenn das Element nicht vorhanden ist und nicht auf der Seite angezeigt wird. Ich habe das else im if else den Test ausführen.

IList<IWebElement> deviceNotFound = driver.FindElements(By.CssSelector("CSS LINK GOES HERE"));
//if the element specified above results in more than 0 elements and is displayed on page execute the following, otherwise execute whats in the else statement
if (deviceNotFound.Count > 0 && deviceNotFound[0].Displayed){
    //script to execute if element is found
} else {
    //Test script goes here.
}

Ich weiß, dass ich bei der Antwort auf das OP etwas spät dran bin. Hoffentlich hilft das jemandem!

Tasha
quelle
5

Versuchen Sie Folgendes: Rufen Sie diese Methode auf und übergeben Sie 3 Argumente:

  1. WebDriver-Variable. // unter der Annahme, dass driver_variable als Treiber verwendet wird.
  2. Das Element, das Sie überprüfen möchten. Sollte von By-Methode bereitstellen. // ex: By.id ("id")
  3. Zeitlimit in Sekunden.

Beispiel: waitForElementPresent (Treiber, By.id ("id"), 10);

public static WebElement waitForElementPresent(WebDriver driver, final By by, int timeOutInSeconds) {

        WebElement element; 

        try{
            driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait() 

            WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); 
            element = wait.until(ExpectedConditions.presenceOfElementLocated(by));

            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //reset implicitlyWait
            return element; //return the element
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null; 
    }
Prabu Ananthakrishnan
quelle
3

Sie können den Code schneller ausführen, indem Sie das Selen-Timeout vor Ihrer try catch-Anweisung kurzschließen.

Ich benutze den folgenden Code, um zu überprüfen, ob ein Element vorhanden ist.

protected boolean isElementPresent(By selector) {
    selenium.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
    logger.debug("Is element present"+selector);
    boolean returnVal = true;
    try{
        selenium.findElement(selector);
    } catch (NoSuchElementException e){
        returnVal = false;
    } finally {
        selenium.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
    }
    return returnVal;
}
EsotericNonsense
quelle
Dies ist, was ich in meinem Code verwende. Ich lasse das Selenium-Timeout auf der Standardeinstellung und verwende es dann.
Nicholas DiPiazza
2
Seit ich diese Antwort geschrieben habe, habe ich gelernt, dass die Verwendung von ExpectedConditions als bessere Form angesehen wird, aber die Verwendung einer try catch-Anweisung immer noch nützlich ist, um festzustellen, ob ein Element nicht vorhanden ist.
EsotericNonsense
Ich stecke auf einer alten Version von Selen fest, weil ich IE8 testen muss. aber ich werde das versuchen, wenn ich upgraden kann
Nicholas DiPiazza
Jedes Mal, wenn Ihre Methode ein implizites Wartezeitlimit festlegt, sollten wir das implizite Warten logischerweise nur einmal festlegen, nachdem das Treiberobjekt initialisiert und das Zeitlimit für die Treibersitzung festgelegt wurde.
Shekhar Swami
3

Schreiben Sie die folgende Funktion / Methode mit Java:

protected boolean isElementPresent(By by){
        try{
            driver.findElement(by);
            return true;
        }
        catch(NoSuchElementException e){
            return false;
        }
    }

Rufen Sie die Methode mit dem entsprechenden Parameter während der Zusicherung auf.

Ripon Al Wasim
quelle
2

Wenn Sie rspec-Webdriver in Ruby verwenden, können Sie dieses Skript verwenden, vorausgesetzt, ein Element sollte wirklich nicht vorhanden sein und es ist ein bestandener Test.

Schreiben Sie diese Methode zuerst aus Ihrer Klasse-RB-Datei

class Test
 def element_present?
    begin
        browser.find_element(:name, "this_element_id".displayed?
        rescue Selenium::WebDriver::Error::NoSuchElementError
            puts "this element should not be present"
        end
 end

Rufen Sie dann in Ihrer Spezifikationsdatei diese Methode auf.

  before(:all) do    
    @Test= Test.new(@browser)
  end

 @Test.element_present?.should == nil

Wenn Ihr Element NICHT vorhanden ist, wird Ihre Spezifikation bestanden, aber wenn das Element vorhanden ist, wird ein Fehler ausgegeben, Test fehlgeschlagen.

Graustufen
quelle
2

Das funktioniert bei mir:

 if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
    //THEN CLICK ON THE SUBMIT BUTTON
}else{
    //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
}
Amstel Bytes
quelle
Hier besteht das gleiche Problem: Was ist, wenn das Element "// * [@ id = 'submit']" nicht existiert? dann wird eine Ausnahme ausgelöst, daher wird die if-Bedingung niemals ausgewertet
MrBCut
1
public boolean isElementDisplayed() {
        return !driver.findElements(By.xpath("...")).isEmpty();
    }
Bogdan Shulga
quelle
1

Persönlich greife ich immer zu einer Mischung der oben genannten Antworten und erstelle eine wiederverwendbare statische Utility-Methode, die den folgenden size() > 0Vorschlag verwendet:

public Class Utility {
   ...
   public static boolean isElementExist(WebDriver driver, By by) {
      return driver.findElements(by).size() > 0;
   ...
}

Das ist ordentlich, wiederverwendbar, wartbar ... all das gute Zeug ;-)

Charlie Seligman
quelle
0

Um festzustellen, ob ein bestimmtes Element vorhanden ist oder nicht, müssen wir die Methode findElements () anstelle von findElement () verwenden.

int i=driver.findElements(By.xpath(".......")).size();
if(i=0)
System.out.println("Element is not present");
else
System.out.println("Element is present");

Das funktioniert für mich. Schlagen Sie mir vor, wenn ich falsch liege.

Subbarao Gaddam
quelle
0

Dies sollte es tun:

try {
    driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
    //do what you need here if you were expecting
    //the element wouldn't exist
}
Scott Helme
quelle
0

Ich gebe meinen Codeausschnitt. Die folgende Methode prüft also, ob auf einer Seite eine zufällige Webelement -Schaltfläche " Neue Anwendung erstellen " vorhanden ist oder nicht. Beachten Sie, dass ich die Wartezeit als 0 Sekunden verwendet habe.

public boolean isCreateNewApplicationButtonVisible(){
    WebDriverWait zeroWait = new WebDriverWait(driver, 0);
    ExpectedCondition<WebElement> c = ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@value='Create New Application']"));
    try {
        zeroWait.until(c);
        logger.debug("Create New Application button is visible");
        return true;
    } catch (TimeoutException e) {
        logger.debug("Create New Application button is not visible");
        return false;
    }
}
Rambo7
quelle
0

Ich würde so etwas verwenden (mit Scala [der Code in altem "gutem" Java 8 könnte diesem ähnlich sein]):

object SeleniumFacade {

  def getElement(bySelector: By, maybeParent: Option[WebElement] = None, withIndex: Int = 0)(implicit driver: RemoteWebDriver): Option[WebElement] = {
    val elements = maybeParent match {
      case Some(parent) => parent.findElements(bySelector).asScala
      case None => driver.findElements(bySelector).asScala
    }
    if (elements.nonEmpty) {
      Try { Some(elements(withIndex)) } getOrElse None
    } else None
  }
  ...
}

also dann,

val maybeHeaderLink = SeleniumFacade getElement(By.xpath(".//a"), Some(someParentElement))
ses
quelle
0

Der einfachste Weg, den ich in Java gefunden habe, ist:

List<WebElement> linkSearch=  driver.findElements(By.id("linkTag"));
int checkLink=linkSearch.size();
if(checkLink!=0){  //do something you want}
back2back
quelle
0

Sie können implizites Warten versuchen:

WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));

Oder Sie können versuchen, explizit zu warten:

IWebDriver driver = new FirefoxDriver();
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
    {
        return d.FindElement(By.Id("someDynamicElement"));
    });

Explicit prüft vor einer Aktion, ob ein Element vorhanden ist. Implizites Warten kann an jeder Stelle im Code aufgerufen werden. Zum Beispiel nach einigen AJAX-Aktionen.

Weitere Informationen finden Sie auf der SeleniumHQ-Seite

streser
quelle