WebDriver: vérifier si un élément existe? [dupliquer]

cette question a déjà une réponse ici:

Comment vérifier si un élément existe avec un pilote web?

est-ce que l'utilisation d'un try catch est vraiment la seule façon possible?

boolean present;
try {
   driver.findElement(By.id("logoutLink"));
   present = true;
} catch (NoSuchElementException e) {
   present = false;
}
101
demandé sur Ralph 2011-06-29 17:17:40

10 réponses

vous pouvez alternativement faire:

driver.findElements( By.id("...") ).size() != 0

, Qui enregistre le méchant try/catch

185
répondu Mike Kwan 2011-06-29 13:57:49

Je suis d'accord avec la réponse de Mike, mais il y a une attente implicite de 3 secondes si aucun élément n'est trouvé qui peut être activé/désactivé ce qui est utile si vous effectuez cette action beaucoup:

driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
boolean exists = driver.findElements( By.id("...") ).size() != 0
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

mettre cela dans une méthode utilitaire devrait améliorer la performance si vous effectuez beaucoup de tests

44
répondu Edd 2012-01-09 14:57:31

comme le commentaire l'indique, c'est en C# Pas Java mais l'idée est la même. J'ai fait des recherches approfondies sur cette question et en fin de compte, le problème est que FindElement renvoie toujours une exception lorsque l'élément n'existe pas. Il n'y a pas d'option surchargée qui vous permette d'obtenir null ou quoi que ce soit d'autre. Voilà pourquoi je préfère cette solution aux autres.

  1. retourner une liste d'éléments puis vérifier si la taille de la liste est 0 fonctionne, mais vous perdez la fonctionnalité que façon. Vous ne pouvez pas faire une .cliquez sur() sur une collection de liens, même si la taille de la collection est 1.
  2. vous pourriez affirmer que l'élément existe mais souvent cela arrête vos essais. Dans certains cas, j'ai un lien supplémentaire à cliquer en fonction de la façon dont je suis arrivé à cette page et je veux le cliquer s'il existe ou passer à autre chose.
  3. c'est seulement lent si vous ne réglez pas le pilote de temporisation .Gérer.)(Timeouts.)(ImplicitlyWait (TimeSpan.Fromsecondes (0));
  4. c'est en fait très simple et élégant une fois que la méthode est créée. En utilisant FindElementSafe au lieu de FindElement , Je ne" vois "pas le bloc laid try/catch et je peux utiliser une méthode simple existe . Cela ressemblerait à quelque chose comme ceci:

    IWebElement myLink = driver.FindElementSafe(By.Id("myId"));
    if (myLink.Exists)
    {
       myLink.Click();
    }
    

, Voici comment étendre 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.Existe

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

vous pourriez utiliser le polymorphisme pour modifier L'instance de classe IWebDriver de FindElement, mais c'est une mauvaise idée du point de vue de la maintenance.

6
répondu Brantley Blanchard 2013-08-05 20:24:55

cela fonctionne pour moi à chaque fois:

    if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
        //THEN CLICK ON THE SUBMIT BUTTON
    }else{
        //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
    }
3
répondu Amstel Bytes 2014-06-17 02:19:54

vous pouvez faire une affirmation.

voir l'exemple

driver.asserts().assertElementFound("Page was not loaded",
By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);

vous pouvez utiliser ce qui est natif:

public static void waitForElementToAppear(Driver driver, By selector, long timeOutInSeconds, String timeOutMessage) {
    try {
      WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
      wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
    } catch (TimeoutException e) {
      throw new IllegalStateException(timeOutMessage);
    }
  }
3
répondu Ran Adler 2014-08-27 05:51:02

écrire la méthode suivante en utilisant Java:

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

appelez la méthode ci-dessus pendant l'affirmation.

2
répondu Ripon Al Wasim 2015-03-16 07:03:05

j'ai étendu la mise en œuvre de WebDriver de sélénium, dans mon cas HtmlUnitDriver pour exposer une méthode

public boolean isElementPresent(By by){}

comme ceci:

  1. vérifier si la page est chargée dans un délai imparti.
  2. une fois la page chargée, j'abaisse implicitement le temps d'attente du WebDriver à quelques millisecondes, dans mon cas 100 mills, devrait probablement fonctionner avec 0 mills aussi.
  3. appeler findElements (By), Le WebDriver même si ne permettra pas de trouver l'élément attendre que le temps à partir de ci-dessus.
  4. remonter le implicitement temps d'attente pour l'avenir de chargement d'une page

Voici mon 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);
    }   
}

Utilisation:

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");
}
1
répondu Lotzy 2014-06-17 14:54:25
String link = driver.findElement(By.linkText(linkText)).getAttribute("href")

cela vous donnera le lien vers lequel l'élément pointe.

0
répondu user1549161 2012-12-19 20:12:06

avec la version 2.21.0 de sélénium-java.jar, vous pouvez le faire;

driver.findElement(By.id("...")).isDisplayed()
-5
répondu nu1silva 2012-04-25 07:39:17

si je comprends bien, c'est la façon par défaut d'utiliser le pilote web.

-7
répondu Pål Brattberg 2011-06-29 13:21:59