Selenium c # Webdriver: Espere hasta que el elemento esté presente

Quiero asegurarme de que haya un elemento presente antes de que el controlador web empiece a hacer cosas.

Estoy tratando de hacer que algo como esto funcione:

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

Principalmente estoy luchando por configurar la función anynomous.

Alternativamente, puede usar la espera implícita:

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

Una espera implícita es decirle a WebDriver que sondee el DOM durante un cierto período de tiempo cuando intente encontrar un elemento o elementos si no están disponibles de inmediato. La configuración predeterminada es 0. Una vez configurado, la espera implícita se establece para la vida de la instancia del objeto WebDriver.

El uso de la solución proporcionada por Mike Kwan puede tener un impacto en el rendimiento general de las pruebas, ya que la espera implícita se utilizará en todas las llamadas FindElement. Muchas veces querrá que FindElement falle de inmediato cuando un elemento no está presente (está probando una página mal formada, elementos faltantes, etc.). Con la espera implícita, estas operaciones esperarían a que expirara todo el tiempo de espera antes de lanzar la excepción. La espera implícita predeterminada se establece en 0 segundos.

He escrito un pequeño método de extensión para IWebDriver que agrega un parámetro de tiempo de espera (en segundos) al método FindElement (). Es bastante autoexplicativo:

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

No guardé el objeto WebDriverWait en caché, ya que su creación es muy económica, esta extensión se puede usar simultáneamente para diferentes objetos WebDriver, y solo hago optimizaciones cuando sea necesario.

El uso es directo:

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

También puedes usar

ExpectedConditions.ElementExists

Entonces buscarás una disponibilidad de elementos así

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

Fuente

Aquí hay una variación de la solución de @ Loudenvier que también funciona para obtener múltiples elementos:

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

Inspirado por la solución de Loudenvier, aquí hay un método de extensión que funciona para todos los objetos ISearchContext, no solo para IWebDriver, que es una especialización de los primeros. Este método también admite esperar hasta que se muestre el 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; }); } } 

Ejemplo de uso:

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

Confundí la función anyomous con el predicado. Aquí hay un pequeño método de ayuda:

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

Puedes encontrar algo como esto en C #.

Esto es lo que utilicé en JUnit – Selenio

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

Importar paquetes relacionados

El comando clickAndWait no se convierte cuando elige el formato de Webdriver en el IDE de Selenium. Aquí está la solución. Agregue la línea de espera a continuación. Siendo realistas, el problema fue el clic o evento que sucedió antes de esta línea 1 en mi código C #. Pero realmente, solo asegúrese de tener un WaitForElement antes de cualquier acción en la que haga referencia a un objeto “By”.

Código HTML:

 xxxxx 

C # / NUnit code:

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

Pitón:

 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')) 

de EC, puede elegir otras condiciones y pruebe esto: http://selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions

Espera explícita

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

Ejemplo:

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

Prueba este código:

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

No desea esperar demasiado antes de que el elemento cambie. En este código, el controlador web espera hasta 2 segundos antes de continuar.


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

Veo múltiples soluciones ya publicadas que funcionan muy bien. Sin embargo, en caso de que alguien necesite algo más, ¡pensé en publicar dos soluciones que utilicé personalmente en el selenium C # para probar si hay un elemento presente! Espero que ayude, ¡salud!

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

Aquí está el segundo

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

Usó Rn222 y Aknuds1 para usar un ISearchContext que devuelve un solo elemento o una lista. Y se puede especificar un número mínimo de elementos:

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

Ejemplo de uso:

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

Estaba buscando cómo esperar en el selenium por la condición, aterrizó en este hilo y aquí está lo que uso ahora:

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

ReadCell(row, col) != "" Puede ser cualquier condición. De esta manera porque:

  • es mio
  • permite enlining
  new WebDriverWait(driver, TimeSpan.FromSeconds(10)). Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container")))); 

La primera respuesta es buena, mi problema fue que las excepciones no controladas no cerraron correctamente el controlador web y mantuvieron el mismo primer valor que había usado, que era de 1 segundo.

Si tienes el mismo problema

restart you visual studio y asegúrese de que all the exceptions are handled correctamente.