Selenium c # Webdriver: Aguarde até que o elemento esteja presente

Eu quero ter certeza de que um elemento esteja presente antes que o webdriver comece a fazer as coisas.

Estou tentando fazer algo assim para funcionar:

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

Eu estou lutando principalmente como configurar a function anynous ..

Como alternativa, você pode usar espera implícita:

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

Uma espera implícita é informar ao WebDriver para pesquisar o DOM por um determinado período de tempo ao tentar localizar um elemento ou elementos se eles não estiverem disponíveis imediatamente. A configuração padrão é 0. Depois de configurada, a espera implícita é definida para a duração da instância do object WebDriver.

Usar a solução fornecida por Mike Kwan pode ter um impacto no desempenho geral do teste, já que a espera implícita será usada em todas as chamadas do FindElement. Muitas vezes você desejará que o FindElement falhe imediatamente quando um elemento não estiver presente (você está testando uma página malformada, elementos ausentes, etc.). Com a espera implícita, essas operações esperariam que todo o tempo limite expirasse antes de lançar a exceção. A espera implícita padrão é definida como 0 segundo.

Eu escrevi um pequeno método de extensão para o IWebDriver que adiciona um parâmetro de tempo limite (em segundos) ao método FindElement (). É 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); } } 

Não armazenei em cache o object WebDriverWait, pois sua criação é muito barata, essa extensão pode ser usada simultaneamente para diferentes objects WebDriver, e só faço otimizações quando necessário.

O uso é direto:

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

Você também pode usar

ExpectedConditions.ElementExists

Então você vai procurar por uma disponibilidade de elementos assim

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

Fonte

Aqui está uma variação da solução da @ Loudenvier que também funciona para obter vários 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 pela solução de Loudenvier, aqui está um método de extensão que funciona para todos os objects ISearchContext, não apenas para o IWebDriver, que é uma especialização do primeiro. Esse método também suporta espera até que o elemento seja exibido.

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

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

Confundi a function anyomous com predicado. Aqui está um pequeno método de ajuda:

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

Você pode descobrir algo assim em c #.

Isto é o que eu usei no JUnit – Selenium

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

Importar pacotes relacionados

O comando clickAndWait não é convertido quando você escolhe o formato Webdriver no Selenium IDE. Aqui está a solução. Adicione a linha de espera abaixo. Realisticamente, o problema foi o clique ou evento que aconteceu antes desta linha 1 no meu código C #. Mas, na verdade, apenas certifique-se de ter um WaitForElement antes de qualquer ação em que você esteja fazendo referência a um object “By”.

Código HTML:

 xxxxx 

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

Python:

 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 você pode escolher outras condições, bem como tentar isto: http://selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions

Espera Explícita

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

Exemplo:

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

Experimente este código:

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

Você não quer esperar muito antes que o elemento seja alterado. Neste código, o webdriver aguarda até 2 segundos antes de continuar.


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

Eu vejo várias soluções já postadas que funcionam muito bem! No entanto, apenas no caso de alguém precisar de outra coisa, eu pensei em postar duas soluções que eu pessoalmente usei em selenium C # para testar se um elemento está presente! Espero que ajude, vivas!

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

Aqui é o 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; } } 

Usado Rn222 e Aknuds1 para usar um ISearchContext que retorna um único elemento ou uma lista. E um número mínimo de elementos pode ser especificado:

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

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

Estava pesquisando como esperar em condição de selenium, pousou neste segmento e aqui está o que eu uso agora:

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

ReadCell(row, col) != "" Pode ser qualquer condição. Assim, porque:

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

A primeira resposta é boa, meu problema era que as exceções não tratadas não fechavam o driver da Web corretamente e mantinham o mesmo valor inicial que eu usava, que era de 1 segundo.

Se você pegar o mesmo problema

restart you visual studio e garanta que all the exceptions are handled corretamente.