Tester si l'élément est présent à l'aide de Selenium WebDriver?

163

Existe-t-il un moyen de tester si un élément est présent? Toute méthode findElement se terminerait par une exception, mais ce n'est pas ce que je veux, car il se peut qu'un élément ne soit pas présent et que ce n'est pas grave, ce n'est pas un échec du test, donc une exception ne peut pas être la solution.

J'ai trouvé ce post: Selenium c # Webdriver: Attendez que l'élément soit présent Mais c'est pour C # et je ne suis pas très bon dans ce domaine. Quelqu'un peut-il traduire le code en Java? Je suis désolé les gars, je l'ai essayé dans Eclipse mais je ne le comprends pas directement dans le code Java.

Voici le 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);
    }
}
testeur
la source
J'ai quelques méthodes qui fonctionnent très efficacement pour rechercher un objet, mais cela dépend de ce que vous voulez en faire. par exemple voulez-vous chercher l'élément jusqu'à ce qu'il existe, voulez-vous le chercher jusqu'à ce qu'il n'existe plus ou voulez-vous simplement essayer de le trouver?
CBRRacer
1
Java est très similaire à C # Je pense que l'un des principaux problèmes que vous rencontrez ici est en java, c'est WebElement au lieu de IWebElement
CBRRacer
Connaissez-vous la méthode d'attente implicite? En configurant cela au début du test, vous n'avez jamais à vérifier l'existence d'un élément car il utilise la valeur d'attente implicite pour interroger, mais si elle dépasse cette valeur, il lèvera une exception
Bob Evans
Voici mon article sur WebDriverWait en Java: WebDriverWait
Si l'un ou l'autre des cas est correct, cela peut être problématique pour les performances des tests, car le temps d'attente associé à l'attente d'un élément que vous ne pensez pas exister s'additionne vraiment. J'ai utilisé quelques hacks pour contourner le temps d'attente, mais je n'ai pas encore trouvé de solution vraiment propre pour cela.
mrfreester

Réponses:

277

Utilisez à la findElementsplace de findElement.

findElements renverra une liste vide si aucun élément correspondant n'est trouvé au lieu d'une exception.

Pour vérifier qu'un élément est présent, vous pouvez essayer ceci

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

Cela retournera vrai si au moins un élément est trouvé et faux s'il n'existe pas.

La documentation officielle recommande cette méthode:

findElement ne doit pas être utilisé pour rechercher des éléments non présents, utilisez à la place findElements (By) et affirmez une réponse de longueur nulle.

el roso
la source
32
Cela ajoutera beaucoup de temps à l'exécution de vos tests. Vous ne pouvez pas utiliser cette technique partout.
Droogans
8
@Droogans - Je n'ajouterai pas de temps à vos tests. La raison pour laquelle ce n'est pas le cas est que l'attente implicite par défaut est toujours de 0. Si vous augmentez l'attente implicite par défaut, alors je suis d'accord que ce serait le cas, mais cela ne semble pas être le cas ici.
djangofan le
1
Bon appel djangofan! J'ai utilisé avec succès cette stratégie en modifiant l'attente implicite des délais d'expiration du pilote à zéro, puis en la remettant à sa valeur précédente.
emery
3
Cela a donné une exception NoSuchElementFound, ce qui est dommage car j'espérais l'utiliser pour éviter d'attraper cette exception dans une instance donnée.
1
Un moyen beaucoup plus simple est d'utiliser: if (driver.getPageSource (). Contains ("Un texte dans la page")) {} Si la page contient ce texte alors la condition sera vraie, sinon elle sera fausse et vous pourrez coder en conséquence.
pradyot
56

Qu'en est-il d'une méthode privée qui recherche simplement l'élément et détermine s'il est présent comme ceci:

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

Ce serait assez facile et fait le travail.

Edit: vous pouvez même aller plus loin et prendre un By elementLocatorcomme paramètre, éliminant les problèmes si vous voulez trouver l'élément par autre chose que id.

Dennis
la source
3
Oui, c'est la voie à suivre. Je ne comprends pas pourquoi les gens ignorent cette façon et comptent les éléments correspondants pour voir si le résultat est égal à 0.
Ralph Lavelle
45
Eh bien, je dois dire que l'utilisation d'exceptions pour réguler le déroulement du programme n'est pas la meilleure solution.
Dennis
2
Hein? C'était ta suggestion! C'est une bonne façon de procéder si votre test s'attend à ne pas trouver l'élément. Comme vous le montrez, renvoyez simplement null et assert.isnull ou isnotnull, ce qui est un moyen significatif de tester si une chose existe.
Ralph Lavelle
2
Au cas où j'aurais mal interprété la question «y a-t-il un moyen de tester si un élément est présent? faux, je serai heureux d'apprendre pourquoi votre opinion diffère sur la question de savoir si c'est une réponse légitime ou non.
Dennis
voudra peut-être réduire le temps d'attente. Pour le moment, si l'élément n'existe pas, vous devez attendre "30 secondes" avant que la fonction ne renvoie false
Jason Smiley
14

J'ai trouvé que cela fonctionne pour Java:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);
Tango Ben
la source
18
presenceOfElementLocatedlancera une exception si l'élément n'est pas trouvé lors d'une tentative particulière. Pour éviter cela, ajoutez une wait.ignoring(NoSuchElementException.class);instruction entre la première et la deuxième ligne.
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);
}
RedDeckGagne
la source
5

J'ai eu le même problème. Pour moi, selon le niveau d'autorisation d'un utilisateur, certains liens, boutons et autres éléments ne s'afficheront pas sur la page. Une partie de ma suite testait que les éléments qui DEVRAIENT manquer, le sont. J'ai passé des heures à essayer de comprendre cela. J'ai finalement trouvé la solution parfaite.

Cela indique au navigateur de rechercher tous les éléments en fonction spécifiés. S'il en résulte0 , cela signifie qu'aucun élément basé sur la spécification n'a été trouvé. Ensuite, le code exécute une instruction if pour me faire savoir qu'il n'a pas été trouvé.

C'est dans C#, donc des traductions devraient être faites Java. Mais ça ne devrait pas être trop dur.

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

Il existe également un autre chemin que vous pouvez emprunter en fonction de ce dont vous avez besoin pour votre test.

L'extrait de code suivant vérifie si un élément très spécifique existe sur la page. En fonction de l'existence de l'élément, le test exécute un if else.

Si l'élément existe et est affiché sur la page, j'ai console.write m'en suis informé et je passe à autre chose. Si l'élément en question existe, je ne peux pas exécuter le test dont j'avais besoin, ce qui est le principal raisonnement derrière la nécessité de le configurer.

Si l'élément n'existe pas et n'est pas affiché sur la page. J'ai le else dans le if else exécuter le test.

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.
}

Je sais que je suis un peu en retard sur la réponse au PO. Espérons que cela aide quelqu'un!

Tasha
la source
5

Essayez ceci: Appelez cette méthode et passez 3 arguments:

  1. Variable WebDriver. // en supposant driver_variable comme pilote.
  2. L'élément que vous allez vérifier. Devrait fournir par méthode. // ex: By.id ("id")
  3. Limite de temps en secondes.

Exemple: waitForElementPresent (driver, 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
la source
3

Vous pouvez accélérer l'exécution du code en raccourcissant le délai d'expiration du sélénium avant votre instruction try catch.

J'utilise le code suivant pour vérifier si un élément est présent.

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;
}
Ésotérique
la source
C'est ce que j'utilise dans mon code. Je laisse le délai d'expiration de Selenium sur la valeur par défaut, puis je l'utilise.
Nicholas DiPiazza
2
Depuis l'écriture de cette réponse, j'ai appris que l'utilisation de ExpectedConditions est considérée comme une meilleure forme, mais l'utilisation d'une instruction try catch est toujours utile pour tenter de déterminer si un élément n'est pas présent.
EsotericNonsense
Je suis coincé sur une ancienne version de sélénium car je dois tester IE8. mais je vais essayer ça quand je
pourrai
Chaque fois que votre méthode définira un délai d'attente implicite, mais logiquement, nous ne devrions définir l'attente implicite qu'une seule fois après l'initialisation de l'objet pilote et le délai d'attente est défini sur la session du pilote.
Shekhar Swami
3

Écrivez la fonction / les méthodes suivantes en utilisant Java:

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

Appelez la méthode avec le paramètre approprié lors de l'assertion.

Ripon Al Wasim
la source
2

si vous utilisez rspec-Webdriver dans ruby, vous pouvez utiliser ce script en supposant qu'un élément ne devrait vraiment pas être présent et que le test a réussi.

Commencez par écrire cette méthode à partir de votre fichier de classe RB

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

Ensuite, sur votre fichier de spécifications, appelez cette méthode.

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

 @Test.element_present?.should == nil

Si votre élément n'est PAS présent, votre spécification passera, mais si l'élément est présent, cela générera une erreur, le test a échoué.

gris
la source
2

Cela fonctionne pour moi:

 if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
    //THEN CLICK ON THE SUBMIT BUTTON
}else{
    //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
}
Octets Amstel
la source
le même problème existe ici: que se passe-t-il si l'élément "// * [@ id = 'submit']" n'existe pas? alors une exception sera levée, donc le conditionnel if ne s'évalue jamais
MrBCut
1
public boolean isElementDisplayed() {
        return !driver.findElements(By.xpath("...")).isEmpty();
    }
Bogdan Shulga
la source
1

Personnellement, je choisis toujours un mélange des réponses ci-dessus et crée une méthode utilitaire statique réutilisable qui utilise la size() > 0suggestion:

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

C'est soigné, réutilisable, maintenable ... toutes ces bonnes choses ;-)

Charlie Seligman
la source
0

Pour trouver qu'un élément particulier est présent ou non, nous devons utiliser la méthode findElements () au lieu de findElement ().

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

cela fonctionne pour moi .. suggérez-moi si je me trompe.

Subbarao Gaddam
la source
0

Cela devrait le faire:

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
la source
0

Donner mon extrait de code. Ainsi, la méthode ci-dessous vérifie si un bouton d' élément Web aléatoire `` Créer une nouvelle application '' existe sur une page ou non. Notez que j'ai utilisé la période d'attente de 0 seconde.

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
la source
0

J'utiliserais quelque chose comme (avec Scala [le code dans l'ancien "bon" Java 8 peut être similaire à ceci]):

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
  }
  ...
}

Donc alors,

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

Le moyen le plus simple que j'ai trouvé en Java est:

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

Vous pouvez essayer une attente implicite:

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"));

Ou vous pouvez essayer une attente explicite:

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 vérifiera si l'élément est présent avant une action. Une attente implicite peut être appelée à chaque endroit du code. Par exemple après quelques actions AJAX.

Plus vous pouvez trouver sur la page SeleniumHQ

streser
la source