2012-07-31 4 views
51

Sto cercando qualcosa di simile a waitForElementPresent per verificare se l'elemento viene visualizzato prima di fare clic su di esso. Ho pensato che questo può essere fatto da implicitWait, così ho usato il seguente:WebDriver - attendere elemento utilizzando Java

driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); 

e quindi fare clic su da

driver.findElement(By.id(prop.getProperty(vName))).click(); 

Purtroppo, a volte attende per l'elemento e, a volte no. Ho guardato per un po 'e ho trovato questa soluzione:

for (int second = 0;; second++) { 
      Thread.sleep(sleepTime); 
      if (second >= 10) 
       fail("timeout : " + vName); 
      try { 
       if (driver.findElement(By.id(prop.getProperty(vName))) 
         .isDisplayed()) 
        break; 
      } catch (Exception e) { 
       writeToExcel("data.xls", e.toString(), 
         parameters.currentTestRow, 46); 
      } 
     } 
     driver.findElement(By.id(prop.getProperty(vName))).click(); 

Ed è aspettato tutto bene, ma prima del timeout è dovuto attendere 10 volte 5, 50 secondi. Un po 'troppo. Così ho impostato implicitamente l'attesa per 1sec e tutto sembrava a posto fino ad ora. Perché ora alcune cose aspettano 10 secondi prima del timeout ma alcune altre cose scadono dopo 1 secondo.

Come si copre l'attesa dell'elemento presente/visibile nel codice? Ogni suggerimento è apprezzabile.

risposta

100

Ecco come lo faccio nel mio codice.

WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds); 
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>)); 

o

wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>)); 

per essere precisi.

Consulta anche:

+1

Grazie! Se solo avessi saputo prima su questa classe la mia vita sarebbe stata più facile :) – tom

+0

Come faccio ad incorporare il tuo codice in questo formato?\t '@FindBy (how = How.ID, using =" signup-button ") \t WebElement signUpButton;' Inoltre, ho ancora un NPE con il tuo codice. Sembra che stia cercando di ottenere elementToBeClickable. Come possiamo usare questo metodo quando l'elemento non è caricato? – HelloWorldNoMore

-1

La dichiarazione di attesa sopra è un bell'esempio di attesa esplicita.

Come attese esplicite sono attese intelligenti che sono confinate a un particolare elemento web (come menzionato in x-path sopra).

Tramite l'uso di attese esplicite, si sta praticamente dicendo a WebDriver che al massimo è di aspettare le unità X (qualunque cosa tu abbia dato come timeoutInSeconds) di tempo prima che si arrenda.

+2

Aggiungi un po 'di snippet di codice alla tua risposta, in quanto altri utenti potrebbero ordinare le risposte in modo diverso e il contesto per "Sopra" potrebbe cambiare per loro. –

3

È possibile utilizzare attesa esplicita o perfetto Attendere

Esempio di Wait esplicita -

WebDriverWait wait = new WebDriverWait(WebDriverRefrence,20); 
WebElement aboutMe; 
aboutMe= wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("about_me")));  

Esempio di Wait Fluent -

Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)        
.withTimeout(20, TimeUnit.SECONDS)   
.pollingEvery(5, TimeUnit.SECONDS)   
.ignoring(NoSuchElementException.class);  

    WebElement aboutMe= wait.until(new Function<WebDriver, WebElement>() {  
public WebElement apply(WebDriver driver) { 
return driver.findElement(By.id("about_me"));  
} 
}); 

Scegli questa TUTORIAL per maggiori dettagli.

1

Stiamo avendo un sacco di condizioni di gara con elementToBeClickable. Vedi https://github.com/angular/protractor/issues/2313. Qualcosa lungo queste linee ha funzionato abbastanza bene anche se un po 'di forza bruta

Awaitility.await() 
     .atMost(timeout) 
     .ignoreException(NoSuchElementException.class) 
     .ignoreExceptionsMatching(
      Matchers.allOf(
       Matchers.instanceOf(WebDriverException.class), 
       Matchers.hasProperty(
        "message", 
        Matchers.containsString("is not clickable at point") 
       ) 
      ) 
     ).until(
      () -> { 
       this.driver.findElement(locator).click(); 
       return true; 
      }, 
      Matchers.is(true) 
     );