it-swarm.com.de

WebDriver: Wie prüfe ich, ob ein Web-Element für ein Seitenobjekt vorhanden ist?

So prüfen Sie, ob ein Element vorhanden ist, wenn Sie Seitenobjekte mit einem Web-Treiber verwenden.

Bisher mache ich es so.

DefaultPage defaultPage = PageFactory.initElements(this.driver,
      DefaultPage.class);
assertTrue(defaultPage.isUserCreateMenuLinkPresent());

Seitenobjekt:

public class DefaultPage {     
    @FindBy(id = "link_i_user_create")
    private WebElement userCreateMenuLink;


    public boolean isUserCreateMenuLinkPresent() {
        try {
            this.userCreateMenuLink.getTagName();
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }
 }

Aber ich kann nicht glauben, dass dieses try/catch so ist, wie man es tun sollte. Was wäre also ein besserer Weg, um zu überprüfen, ob die Elemente vorhanden sind (mit Seitenobjekten)?

18
Ralph

Webdriver ist so konzipiert, dass eine Ausnahme ausgelöst wird, wenn ein Element nicht gefunden wird. Es gibt also keine Methoden, um das Vorhandensein eines Elements in Webdriver zu überprüfen.

Überprüfen Sie dies - http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341

4
dmp

Das Problem ist das Muster selbst. Es verwendet die Annotation @FindBy (wird von PageFactory zum Initiieren der Felder verwendet, die von Proxy umschlossen werden müssen), die die Standardelemente durch ihre Proxy-Instanzen ersetzt, die InvocationHandler enthalten.

Bei jedem Versuch, auf ein Feld zuzugreifen, das mit @FindBy gekennzeichnet ist, versucht der Aufrufhandler, das Element mithilfe des StandardelementLocator zu finden. Das Problem besteht darin, dass die ElementLocator.findElement () - Methode eine TimeoutException/NoSuchElementException auslöst, wenn keine Elemente angezeigt werden das DOM.

public WebElement findElement(SearchContext context) {
   List<WebElement> allElements = findElements(context);
   if (allElements == null || allElements.isEmpty())
      throw new NoSuchElementException("Cannot locate an element using "
      + toString());
   return allElements.get(0);
}

Daher müssen Sie jedes Mal überprüfen, ob ein Element angezeigt wird oder nicht, und Sie müssen nach einer Liste von Elementen suchen und deren Größe überprüfen.

@FindBy(css = "div.custom")
private List<WebElement> elements
...

public isElementPresented(){
   return elements != null && elements.size > 0
}

Eine andere Möglichkeit, dieses Problem zu lösen, besteht darin, Ihre eigene Implementierung von LocatingElementHandler und ElementLocator zu erstellen.

Wenn Sie also Ihre eigene isDisplayed () - Methode benötigen, um false anstelle von Exception zurückzugeben, müssen Sie die findElement () - Methode in ElementLocator durch Folgendes ersetzen:

...
List<WebElement> elements = searchContext.findElements(by)
if(elements != null && elements.size() > 0){
   List<WebElement> visibleElements = []
   elements.each {
      if(it.displayed){
         visibleElements.add(it)
      }
   }
   if(visibleElements.size() > 0){
      return visibleElements.get(0)
   }
}
return null
...

Fügen Sie LocatingElementHandler.invoke () neue Bedingungen hinzu. 

So etwas wie:

element = locator.findElement()
if(element == null){
   if(method.name == "isDisplayed"){
      return false
   }
}

Ich bin kürzlich auf diesen alten Post gestoßen und glaube, dass ich eine Lösung gefunden habe. 

Ich habe eine Seite mit einer Add User-Schaltfläche getestet. Wenn Sie auf die Schaltfläche klicken, werden verschiedene bearbeitbare Textfelder (für Vorname, Nachname, E-Mail usw.) und ein einziges Dropdown-Menü angezeigt. 

Wenn Sie auf eine Cancel-Schaltfläche klicken, verschwinden die Felder und sind nicht mehr vorhanden. Die Verwendung von WebDriverWait mit ExpectedConditions.visibilityOf() würde nicht funktionieren, da die Elemente in der DOM nicht mehr vorhanden waren. 

Ich fand, dass @FindAll eine Lösung für mich war, obwohl ich zugeben muss, dass mein Test bei meiner Liste-Liste auffällig langsam lief.

Für Ihren Code etwa so:

public class DefaultPage {     
@FindAll({@FindBy(id = "link_i_user_create")}) List<WebElement> userCreateMenuLink;


public boolean isUserCreateMenuLinkPresent() {
    if (this.userCreateMenuLink.isEmpty()) fail("Link does not exist");}

Ich kann etwas Ähnliches in meinen eigenen Tests verwenden, und es scheint mir eine verlässliche Möglichkeit zu sein, um die Ausnahme "Kein solches Element" zu umgehen. Es ist im Grunde eine Seitenobjekt-Anpassung des Asserting: driver.findElements(By.locator).size() < 1

1
T.D.

Ich verwende dieses Muster, funktioniert gut für mich:

public void login() 
{
    if (!loginButton.isDisplayed())
    {
        throw new IllegalStateException("Login button is not displayed!");
    } else
    {
        loginButton.click();    
    }        
}

oder:

public boolean loginButtinIsDisplayed() {
    try {
        this.loginButton.getTagName();
        return true;
    } catch (NoSuchElementException e) {
        e.printStackTrace();
        return false;
    }
}
1
prs

C # -Bindungen verwenden:

using System.Collections.Generic;
using System.Linq;

public class DefaultPage 
{
    [FindsBy(How = How.Id, Using = "link_i_user_create")]
    private IList<IWebElement> userCreateMenuLink;

    public bool isUserCreateMenuLinkPresent()
    {
        return userCreateMenuLink.Any();
    }
}

Sie fordern Selenium auf, alle Elemente, die dieser Id entsprechen, zu packen und sie in eine Liste von IWebElement aufzunehmen. Sie rufen dann .Any() in der Liste auf, die als wahr ausgewertet wird, wenn mindestens eine IWebElement gefunden wurde.

0
Pete

Arquillian hat diese Funktion in der Erweiterung Graphene implementiert.

Überprüfen Sie die Funktion ElementLocatorConditionFactory.isPresent() .

Sie tun mehr oder weniger das, was Sie in Ihre Frage geschrieben haben (von ExpectedConditions.findElement in Selenium-support.jar ):

try {
    return driver.findElement(by);
} catch (NoSuchElementException e) {
    throw e;
} catch (WebDriverException e) {
    // [...] some log
    throw e;
}
0
Anthony O.

@Ralph: Ich mache das genauso: try/catch. Ich habe nie einen anderen Weg gefunden ... Sie könnten den try/catch-Block in einer super-Klasse austauschen und ihn generic entwerfen. Mit anderen Worten: Sie könnten eine Methode schreiben, die ein Objekt vom Typ WebElement erwartet. Diese Methode enthält den try/catch-Block und gibt true/false zurück.

Also habe ich die folgende öffentliche Methode in der test framework 's super class geschrieben und kann sie jetzt in jedem page Objekt verwenden:

public boolean isElementExisting(WebElement we) {
    try {
        we.isDisplayed();
        return true;
    } catch(NoSuchElementException e) {
        LOGGER.severe("Element does not exist.");
        return false;
    }
}

Ich weiß nicht, warum dies nicht in WebDriver ... implementiert ist.

Ansonsten könnten Sie WebDriverWait verwenden.

0
Flo Bayer