web-dev-qa-db-fra.com

WebDriver: vérifier si un élément existe?

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

Est-ce que l'utilisation d'une prise d'essai est vraiment le seul moyen possible?

boolean present;
try {
   driver.findElement(By.id("logoutLink"));
   present = true;
} catch (NoSuchElementException e) {
   present = false;
}
114
Ralph

Vous pouvez aussi faire:

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

Qui sauve le méchant essayer/attraper

214
Mike Kwan

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

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

Le fait de le mettre dans une méthode utilitaire devrait améliorer les performances si vous exécutez de nombreux tests.

49
Edd

Comme le commentaire l'a indiqué, ceci est en C # pas Java mais l'idée est la même. J'ai effectué des recherches approfondies sur ce problème et, finalement, le problème est que FindElement renvoie toujours une exception lorsque l'élément n'existe pas. Il n’existe pas d’option surchargée permettant d’obtenir null ou quoi que ce soit d’autre. Voici 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é de cette façon. Vous ne pouvez pas faire un .click () sur une collection de liens même si la taille de la collection est 1.
  2. Vous pouvez affirmer que l'élément existe mais que souvent cela arrête vos tests. Dans certains cas, j'ai un lien supplémentaire à cliquer en fonction de la manière dont je suis arrivé à cette page et je souhaite cliquer dessus si elle existe ou si elle continue.
  3. Ce n'est que lent si vous ne définissez pas le délai d'expiration driver.Manage (). Timeouts (). ImplicitlyWait (TimeSpan.FromSeconds (0));
  4. C'est en fait très simple et élégant une fois la méthode créée. En utilisant FindElementSafe au lieu de FindElement, je ne "vois" pas le bloc try/catch et je peux utiliser une méthode simple Exists. Cela ressemblerait à 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.Exists

    /// <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 pouvez utiliser le polymorphisme pour modifier l'instance de la classe IWebDriver de FindElement, mais c'est une mauvaise idée du point de vue de la maintenance.

8
Brantley Blanchard

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
    }
5
Amstel Bytes

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 ceci c'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
Ran Adler

Ecrivez 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 lors de l'assertion.

2
Ripon Al Wasim

J'ai étendu l'implémentation de Selenium WebDriver, dans mon cas, HtmlUnitDriver pour exposer une méthode

public boolean isElementPresent(By by){}

comme ça:

  1. vérifie si la page est chargée dans un délai donné.
  2. Une fois la page chargée, j'abaisse implicitement le temps d'attente du WebDriver de quelques millisecondes, dans mon cas 100 moulins devraient probablement fonctionner également avec 0 moulins.
  3. appelez findElements (By), le WebDriver, même s'il ne trouve pas l'élément, n'attendra que la durée indiquée ci-dessus.
  4. remonter le temps d'attente implicite pour le chargement futur de la 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);
    }   
}

Usage:

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");
}
2
Lotzy
String link = driver.findElement(By.linkText(linkText)).getAttribute("href")

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

1
user1549161