Selenio c # Webdriver: Wait Until Element is Present

Voglio assicurarmi che un elemento sia presente prima che il webdriver inizi a fare cose.

Sto cercando di far funzionare qualcosa del genere:

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5)); wait.Until(By.Id("login")); 

Mi sto principalmente sforzando su come impostare la funzione anynomous ..

In alternativa puoi usare l’attesa implicita:

 driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10); 

Un’attesa implicita è di dire a WebDriver di interrogare il DOM per una certa quantità di tempo quando si cerca di trovare un elemento o elementi se non sono immediatamente disponibili. L’impostazione predefinita è 0. Una volta impostata, l’attesa implicita viene impostata per la durata dell’istanza dell’object WebDriver.

L’utilizzo della soluzione fornita da Mike Kwan potrebbe avere un impatto sulle prestazioni complessive dei test, poiché l’attesa implicita verrà utilizzata in tutte le chiamate di FindElement. Molte volte vorrai che il FindElement fallisca immediatamente quando un elemento non è presente (stai testando per una pagina malformata, elementi mancanti, ecc.). Con l’attesa implicita, queste operazioni attendono che scada l’intero timeout prima di lanciare l’eccezione. L’attesa implicita predefinita è impostata su 0 secondi.

Ho scritto un piccolo metodo di estensione a IWebDriver che aggiunge un parametro timeout (in secondi) al metodo FindElement (). È abbastanza auto-esplicativo:

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

Non ho memorizzato nella cache l’object WebDriverWait in quanto la sua creazione è molto economica, questa estensione può essere utilizzata simultaneamente per diversi oggetti WebDriver e io faccio solo ottimizzazioni quando è necessario.

L’utilizzo è semplice:

 var driver = new FirefoxDriver(); driver.Navigate().GoToUrl("http://localhost/mypage"); var btn = driver.FindElement(By.CssSelector("#login_button")); btn.Click(); var employeeLabel = driver.FindElement(By.CssSelector("#VCC_VSL"), 10); Assert.AreEqual("Employee", employeeLabel.Text); driver.Close(); 

Puoi anche usare

ExpectedConditions.ElementExists

Quindi cercherai una disponibilità di elementi del genere

 new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login)))); 

fonte

Ecco una variante della soluzione di @Loudenvier che funziona anche per ottenere più elementi:

 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); } public static ReadOnlyCollection FindElements(this IWebDriver driver, By by, int timeoutInSeconds) { if (timeoutInSeconds > 0) { var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds)); return wait.Until(drv => (drv.FindElements(by).Count > 0) ? drv.FindElements(by) : null); } return driver.FindElements(by); } } 

Ispirato dalla soluzione di Loudenvier, ecco un metodo di estensione che funziona per tutti gli oggetti ISearchContext, non solo IWebDriver, che è una specializzazione del primo. Questo metodo supporta anche l’attesa fino alla visualizzazione dell’elemento.

 static class WebDriverExtensions { ///  /// Find an element, waiting until a timeout is reached if necessary. ///  /// The search context. /// Method to find elements. /// How many seconds to wait. /// Require the element to be displayed? /// The found element. public static IWebElement FindElement(this ISearchContext context, By by, uint timeout, bool displayed=false) { var wait = new DefaultWait(context); wait.Timeout = TimeSpan.FromSeconds(timeout); wait.IgnoreExceptionTypes(typeof(NoSuchElementException)); return wait.Until(ctx => { var elem = ctx.FindElement(by); if (displayed && !elem.Displayed) return null; return elem; }); } } 

Esempio di utilizzo:

 var driver = new FirefoxDriver(); driver.Navigate().GoToUrl("http://localhost"); var main = driver.FindElement(By.Id("main")); var btn = main.FindElement(By.Id("button")); btn.Click(); var dialog = main.FindElement(By.Id("dialog"), 5, displayed: true); Assert.AreEqual("My Dialog", dialog.Text); driver.Close(); 

Ho confuso la funzione anomala con predicato. Ecco un piccolo metodo di aiuto:

  WebDriverWait wait; private void waitForById(string id) { if (wait == null) wait = new WebDriverWait(driver, new TimeSpan(0,0,5)); //wait.Until(driver); wait.Until(d => d.FindElement(By.Id(id))); } 

Puoi scoprire qualcosa di simile in C #.

Questo è quello che ho usato in JUnit – Selenium

 WebDriverWait wait = new WebDriverWait(driver, 100); WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit"))); 

Importa pacchetti correlati

Il comando clickAndWait non viene convertito quando si sceglie il formato Webdriver nell’IDE di selenium. Ecco la soluzione. Aggiungi la riga di attesa sotto. Realisticamente, il problema era il clic o l’evento che era accaduto prima di questa riga 1 nel mio codice C #. Ma in realtà, assicurati di avere un WaitForElement prima di qualsiasi azione in cui fai riferimento a un object “By”.

Codice HTML:

 xxxxx 

Codice C # / NUnit:

 driver.FindElement(By.LinkText("z")).Click; driver.WaitForElement(By.LinkText("xxxxx")); driver.FindElement(By.LinkText("xxxxx")).Click(); 
 //wait up to 5 seconds with no minimum for a UI element to be found WebDriverWait wait = new WebDriverWait(_pagedriver, TimeSpan.FromSeconds(5)); IWebElement title = wait.Until((d) => { return d.FindElement(By.ClassName("MainContentHeader")); }); 

Pitone:

 from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By driver.find_element_by_id('someId').click() WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.ID, 'someAnotherId')) 

da EC puoi scegliere altre condizioni e provare questo: http://selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions

Aspetta esplicita

 public static WebDriverWait wait = new WebDriverWait(driver, 60); 

Esempio:

 wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink)); 

Prova questo codice:

  New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed) 

Non vuoi aspettare troppo a lungo prima che l’elemento cambi. In questo codice il webdriver attende fino a 2 secondi prima di continuare.


 WebDriverWait wait = new WebDriverWait (driver, TimeSpan.FromMilliseconds (2000));
 wait.Until (ExpectedConditions.VisibilityOfAllElementsLocatedBy (By.Name ( "html-name")));

Vedo molte soluzioni già pubblicate che funzionano benissimo! Tuttavia, nel caso qualcuno abbia bisogno di qualcos’altro, ho pensato di pubblicare due soluzioni che ho usato personalmente nel C # del selenium per verificare se un elemento è presente! Spero che ti aiuti, evviva!

 public static class IsPresent { public static bool isPresent(this IWebDriver driver, By bylocator) { bool variable = false; try { IWebElement element = driver.FindElement(bylocator); variable = element != null; } catch (NoSuchElementException){ } return variable; } } 

Ecco il secondo

  public static class IsPresent2 { public static bool isPresent2(this IWebDriver driver, By bylocator) { bool variable = true; try { IWebElement element = driver.FindElement(bylocator); } catch (NoSuchElementException) { variable = false; } return variable; } } 
 public bool doesWebElementExist(string linkexist) { try { driver.FindElement(By.XPath(linkexist)); return true; } catch (NoSuchElementException e) { return false; } } 

Utilizzato Rn222 e Aknuds1 per utilizzare un ISearchContext che restituisce un singolo elemento o un elenco. E un numero minimo di elementi può essere specificato:

 public static class SearchContextExtensions { ///  /// Method that finds an element based on the search parameters within a specified timeout. ///  /// The context where this is searched. Required for extension methods /// The search parameters that are used to identify the element /// The time that the tool should wait before throwing an exception ///  The first element found that matches the condition specified public static IWebElement FindElement(this ISearchContext context, By by, uint timeOutInSeconds) { if (timeOutInSeconds > 0) { var wait = new DefaultWait(context); wait.Timeout = TimeSpan.FromSeconds(timeOutInSeconds); return wait.Until(ctx => ctx.FindElement(by)); } return context.FindElement(by); } ///  /// Method that finds a list of elements based on the search parameters within a specified timeout. ///  /// The context where this is searched. Required for extension methods /// The search parameters that are used to identify the element /// The time that the tool should wait before throwing an exception /// A list of all the web elements that match the condition specified public static IReadOnlyCollection FindElements(this ISearchContext context, By by, uint timeoutInSeconds) { if (timeoutInSeconds > 0) { var wait = new DefaultWait(context); wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds); return wait.Until>(ctx => ctx.FindElements(by)); } return context.FindElements(by); } ///  /// Method that finds a list of elements with the minimum amount specified based on the search parameters within a specified timeout.
///
/// The context where this is searched. Required for extension methods /// The search parameters that are used to identify the element /// The time that the tool should wait before throwing an exception /// /// The minimum number of elements that should meet the criteria before returning the list /// If this number is not met, an exception will be thrown and no elements will be returned /// even if some did meet the criteria /// /// A list of all the web elements that match the condition specified public static IReadOnlyCollection FindElements(this ISearchContext context, By by, uint timeoutInSeconds, int minNumberOfElements) { var wait = new DefaultWait(context); if (timeoutInSeconds > 0) { wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds); } // Wait until the current context found the minimum number of elements. If not found after timeout, an exception is thrown wait.Until(ctx => ctx.FindElements(by).Count >= minNumberOfElements); //If the elements were successfuly found, just return the list return context.FindElements(by); } }

Esempio di utilizzo:

 var driver = new FirefoxDriver(); driver.Navigate().GoToUrl("http://localhost"); var main = driver.FindElement(By.Id("main")); // It can be now used to wait when using elements to search var btn = main.FindElement(By.Id("button"),10); btn.Click(); //This will wait up to 10 seconds until a button is found var button = driver.FindElement(By.TagName("button"),10) //This will wait up to 10 seconds until a button is found, and return all the buttons found var buttonList = driver.FindElements(By.TagName("button"),10) //This will wait for 10 seconds until we find at least 5 buttons var buttonsMin= driver.FindElements(By.TagName("button"), 10, 5); driver.Close(); 

Stavo cercando come aspettare in Selenium per le condizioni, sono arrivato in questo thread ed ecco quello che uso ora:

  WebDriverWait wait = new WebDriverWait(m_driver, TimeSpan.FromSeconds(10)); wait.Until(d => ReadCell(row, col) != ""); 

ReadCell(row, col) != "" Può essere qualsiasi condizione. In questo modo perché:

  • è mio
  • consente l’inlining
  new WebDriverWait(driver, TimeSpan.FromSeconds(10)). Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container")))); 

La prima risposta è buona, il mio problema era che le eccezioni non gestite non chiudevano correttamente il driver web e mantenevano lo stesso primo valore che avevo usato che era 1 secondo.

Se si ottiene lo stesso problema

restart you visual studio e assicurati che all the exceptions are handled correttamente.