Verifica se l'elemento è presente utilizzando Selenium WebDriver?


163

C'è un modo per verificare se un elemento è presente? Qualsiasi metodo findElement finirebbe con un'eccezione, ma non è quello che voglio, perché può essere che un elemento non sia presente e che vada bene, che non sia un fallimento del test, quindi un'eccezione non può essere la soluzione.

Ho trovato questo post: Selenium c # Webdriver: Aspetta che l'elemento sia presente Ma questo è per C # e non sono molto bravo in questo. Qualcuno può tradurre il codice in Java? Mi dispiace ragazzi, l'ho provato in Eclipse ma non riesco a inserirlo nel codice Java.

Questo è il codice:

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

Ho un paio di metodi che funzionano in modo molto efficace per verificare la presenza di un oggetto, ma dipende da cosa si vuole fare con esso. ad esempio vuoi cercare l'elemento finché non esiste, vuoi cercarlo fino a quando non esiste più o vuoi solo provare a trovarlo?
CBRRacer,

1
Java è molto simile a C # Penso che uno dei principali problemi in cui ti imbatti sia in Java sia WebElement invece di IWebElement
CBRRacer

Conosci il metodo di attesa implicito? Impostandolo all'inizio del test non devi mai verificare l'esistenza di un elemento poiché utilizza il valore di attesa implicito per eseguire il polling, tuttavia se supera tale valore genererà un'eccezione
Bob Evans,

Ecco il mio post su WebDriverWait in Java: WebDriverWait

Se uno dei due casi va bene, questo può essere problematico per le prestazioni del test, poiché il tempo di attesa associato per l'attesa di un elemento che non ti aspetti di esistere si somma davvero. Ho usato alcuni hack per aggirare i tempi di attesa, ma devo ancora trovare una soluzione veramente pulita per questo.
sig.

Risposte:


277

Usa findElementsinvece di findElement.

findElements restituirà un elenco vuoto se non viene trovato alcun elemento corrispondente anziché un'eccezione.

Per verificare la presenza di un elemento, puoi provare questo

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

Ciò restituirà true se viene trovato almeno un elemento e false se non esiste.

La documentazione ufficiale raccomanda questo metodo:

findElement non dovrebbe essere usato per cercare elementi non presenti, usare findElements (By) e affermare invece una risposta di lunghezza zero.


32
Ciò aggiungerà molto tempo per eseguire i test. Non puoi usare questa tecnica ovunque.
Droogans,

8
@Droogans - Non aggiungerò tempo ai tuoi test. La ragione per cui non lo sarà è perché l'attesa implicita predefinita è ancora 0. Se hai aumentato l'attesa implicita predefinita, sono d'accordo che sarebbe, ma non sembra essere il caso qui.
Djangofan,

1
Buona chiamata Djangofan! Ho usato con successo questa strategia modificando l'attesa implicita dei timeout del driver a zero, quindi riportandola al valore precedente.
smerigliata

3
Questo ha dato un'eccezione NoSuchElementFound, il che è un peccato perché speravo di usarlo per evitare di catturare quell'eccezione in una determinata istanza.

1
Il modo molto più semplice è usare: if (driver.getPageSource (). Contiene ("Un testo nella pagina")) {} Se la pagina contiene questo testo, allora la condizione sarà vera, altrimenti sarà falsa e potrai scrivere codice di conseguenza.
pradyot,

56

Che dire di un metodo privato che cerca semplicemente l'elemento e determina se è presente in questo modo:

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

Questo sarebbe abbastanza facile e fa il lavoro.

Modifica: potresti anche andare oltre e prendere un By elementLocatorparametro as, eliminando i problemi se vuoi trovare l'elemento con qualcosa di diverso da id.


3
Sì, questa è la strada da percorrere. Non capisco perché le persone ignorano in questo modo e contano gli elementi corrispondenti, vedendo se il risultato è 0.
Ralph Lavelle

45
Bene, devo dire che usare Eccezioni per regolare il flusso del programma non è il modo migliore di procedere.
Dennis,

2
Eh? È stato il tuo suggerimento! È un buon modo di procedere se il test prevede di non trovare l'elemento. Come mostri, restituisci null e assert.isnull o isnotnull, che è un modo significativo per verificare se esiste qualcosa.
Ralph Lavelle,

2
Nel caso in cui ho frainteso la domanda "c'è un modo per verificare se un elemento è presente?" sbaglio, sarò felice di sapere perché la tua opinione differisce dal fatto che questa sia o meno una risposta legittima.
Dennis,

potrebbe voler ridurre i tempi di attesa. In questo momento, se l'elemento non esiste, devi attendere "30 secondi" prima che la funzione restituisca false
Jason Smiley,

14

Ho scoperto che questo funziona per Java:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);

18
presenceOfElementLocatedgenererà un'eccezione se l'elemento non viene trovato in alcun tentativo particolare. Per evitare ciò, aggiungi wait.ignoring(NoSuchElementException.class);un'istruzione tra la prima e la seconda riga.
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);
}

5

Ho avuto lo stesso problema. A mio avviso, a seconda del livello di autorizzazione dell'utente, alcuni collegamenti, pulsanti e altri elementi non verranno visualizzati nella pagina. Parte della mia suite stava testando la mancanza degli elementi che DOVREBBE mancare. Ho passato ore a cercare di capirlo. Finalmente ho trovato la soluzione perfetta.

Ciò che fa è dire al browser di cercare qualsiasi e tutti gli elementi in base specificati. Se risulta 0, ciò significa che non è stato trovato alcun elemento basato sulla specifica. Quindi ho il codice eseguire un'istruzione if per farmi sapere che non è stato trovato.

Questo è dentro C#, quindi le traduzioni dovrebbero essere fatte a Java. Ma non dovrebbe essere troppo difficile.

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

C'è anche un altro percorso che puoi seguire a seconda di ciò di cui hai bisogno per il tuo test.

Il frammento seguente sta verificando se esiste un elemento molto specifico nella pagina. A seconda dell'esistenza dell'elemento, ho il test per eseguire un if else.

Se l'elemento esiste e viene visualizzato nella pagina, mi è stato console.writefatto sapere e andare avanti. Se esiste l'elemento in questione, non posso eseguire il test di cui avevo bisogno, che è il ragionamento principale alla base della necessità di configurarlo.

Se l'elemento non esiste e non viene visualizzato nella pagina. Ho l'altro in if else eseguo il 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.
}

So di essere un po 'in ritardo sulla risposta all'OP. Spero che questo aiuti qualcuno!


5

Prova questo: chiama questo metodo e passa 3 argomenti:

  1. Variabile WebDriver. // assumendo driver_variable come driver.
  2. L'elemento che stai per verificare. Dovrebbe fornire dal metodo. // ex: By.id ("id")
  3. Tempo limite in secondi.

Esempio: 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; 
    }

3

È possibile rendere più veloce l'esecuzione del codice abbreviando il timeout del selenio prima dell'istruzione try catch.

Uso il seguente codice per verificare se è presente un elemento.

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

Questo è quello che uso nel mio codice. Lascio il timeout al selenio sul valore predefinito e quindi lo utilizzo.
Nicholas DiPiazza l'

2
Da quando ho scritto questa risposta ho appreso che l'utilizzo di ExpectedConditions è considerato una forma migliore ma l'utilizzo di un'istruzione try catch è comunque utile quando si tenta di determinare se un elemento non è presente.
EsotericNonsense

Sono bloccato su una vecchia versione di selenio perché devo testare IE8. ma ci proverò quando potrò aggiornare
Nicholas DiPiazza il

Ogni volta che il metodo imposterà il timeout di attesa implicito, ma logicamente dovremmo impostare l'attesa implicita solo una volta dopo aver inizializzato l'oggetto driver e il timeout è impostato sulla sessione del driver.
Shekhar Swami,

3

Scrivi la seguente funzione / methos usando Java:

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

Chiamare il metodo con il parametro appropriato durante l'asserzione.


2

se stai usando rspec-Webdriver in ruby, puoi usare questo script supponendo che un elemento non dovrebbe davvero essere presente ed è un test superato.

Innanzitutto, scrivi prima questo metodo dal tuo file RB di classe

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

Quindi, nel tuo file delle specifiche, chiama quel metodo.

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

 @Test.element_present?.should == nil

Se l'elemento NON è presente, le specifiche passeranno, ma se l'elemento è presente, verrà generato un errore, test fallito.


2

Questo funziona per me:

 if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
    //THEN CLICK ON THE SUBMIT BUTTON
}else{
    //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
}

lo stesso problema esiste qui: cosa succede se l'elemento "// * [@ id = 'submit']" non esiste? allora verrà generata un'eccezione, quindi il se condizionale non valuta mai
MrBCut

1
public boolean isElementDisplayed() {
        return !driver.findElements(By.xpath("...")).isEmpty();
    }

1

Personalmente, cerco sempre una combinazione delle risposte precedenti e creo un metodo di utilità statica riutilizzabile che utilizza il size() > 0suggerimento:

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

Questo è pulito, riutilizzabile, mantenibile ... tutta quella roba buona ;-)


0

Per trovare un elemento particolare è presente o no, dobbiamo usare il metodo findElements () invece di 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");

questo ha funzionato per me .. suggeriscimi se sbaglio ..


0

Questo dovrebbe farlo:

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

0

Dare il mio frammento di codice. Pertanto, il metodo seguente controlla se esiste un pulsante " Crea nuova applicazione " su una pagina in modo casuale . Si noti che ho usato il periodo di attesa come 0 secondi.

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

0

Vorrei usare qualcosa del genere (con Scala [il codice nel vecchio "buono" Java 8 potrebbe essere simile a questo]):

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

allora,

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

0

Il modo più semplice che ho trovato in Java è:

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

0

Puoi provare l'attesa implicita:

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

Oppure puoi provare esplicitamente ad aspettare uno:

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

Esplicito verificherà se l'elemento è presente prima di alcune azioni. L'attesa implicita potrebbe essere chiamata in ogni punto del codice. Ad esempio dopo alcune azioni AJAX.

Maggiori informazioni sono disponibili sulla pagina SeleniumHQ

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.