for expectedconditions c# selenium webdriver automated-tests

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



selenium wait (19)

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.


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


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.


Aquí está mi solución, no quiere esperar mucho antes de que el elemento cambie. En este código, el controlador de página espera 2 segundos antes de continuar.

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


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


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


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:

<a href="http://www.google.com">xxxxx</a>

C # / NUnit code:

driver.FindElement(By.LinkText("z")).Click; driver.WaitForElement(By.LinkText("xxxxx")); driver.FindElement(By.LinkText("xxxxx")).Click();


Espera explícita

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

Ejemplo:

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


Estaba buscando cómo esperar en el selenio 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

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 { /// <summary> /// Find an element, waiting until a timeout is reached if necessary. /// </summary> /// <param name="context">The search context.</param> /// <param name="by">Method to find elements.</param> /// <param name="timeout">How many seconds to wait.</param> /// <param name="displayed">Require the element to be displayed?</param> /// <returns>The found element.</returns> public static IWebElement FindElement(this ISearchContext context, By by, uint timeout, bool displayed=false) { var wait = new DefaultWait<ISearchContext>(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();


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.


Prueba este código:

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


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


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

Source


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


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


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


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


//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<IWebElement>((d) => { return d.FindElement(By.ClassName("MainContentHeader")); });


public bool doesWebElementExist(string linkexist) { try { driver.FindElement(By.XPath(linkexist)); return true; } catch (NoSuchElementException e) { return false; } }