Selenium c#Webdriver:等到元素存在
我想在webdriver开始做东西之前确定一个元素。
我试图得到这样的工作:
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5)); wait.Until(By.Id("login"));
我主要是在努力如何设置anynomousfunction..
或者,您可以使用隐式等待:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
一个隐含的等待就是告诉WebDriver在查找一个或多个元素(如果不是立即可用的)时轮询DOM一段时间。 默认设置为0.一旦设置,隐式等待就设置为WebDriver对象实例的生命周期。
使用Mike Kwan提供的解决scheme可能会对整体testing性能产生影响,因为在所有FindElement调用中将使用隐式等待。 很多时候,你会希望FindElement在元素不存在的时候马上失败(你正在testing格式不正确的页面,缺less元素等等)。 在隐式等待的情况下,这些操作会在抛出exception之前等待整个超时过期。 默认的隐含等待设置为0秒。
我写了一个扩展方法给IWebDriver,它为FindElement()方法增加了一个超时(以秒为单位)参数。 这是不言而喻的:
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); } }
我没有cachingWebDriverWait对象,因为它的创build非常便宜,这个扩展可能同时用于不同的WebDriver对象,而且我只在最终需要时才进行优化。
用法很简单:
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();
你也可以使用
ExpectedConditions.ElementExists
所以你会search这样的元素可用性
new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login))));
资源
这是@ Loudenvier解决scheme的一个变种,也可以用于获取多个元素:
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); } }
受Loudenvier解决scheme的启发,这里有一个适用于所有ISearchContext对象的扩展方法,而不仅仅是前者的专门化IWebDriver。 此方法也支持等待,直到显示元素。
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; }); } }
用法示例:
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();
我用谓词混淆了不规范的函数。 下面是一个小帮手的方法:
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))); }
你可以在C#中find这样的东西。
这是我在JUnit中使用的 – Selenium
WebDriverWait wait = new WebDriverWait(driver, 100); WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));
做导入相关的包
在Selenium IDE中selectWebdriver格式时,clickAndWait命令不会被转换。 这是解决方法。 在下面添加等待线。 实际上,问题是在我的C#代码中的这一行之前发生的点击或事件。 但是,确实,在引用“By”对象的任何操作之前,请确保您有一个WaitForElement。
HTML代码:
<a href="http://www.google.com">xxxxx</a>
C#/ NUnit代码:
driver.FindElement(By.LinkText("z")).Click; driver.WaitForElement(By.LinkText("xxxxx")); driver.FindElement(By.LinkText("xxxxx")).Click();
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'))
从EC你可以select其他条件,以及试试这个: http : //selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions
显式等待
public static WebDriverWait wait = new WebDriverWait(driver, 60);
例:
wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink));
//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")); });
我看到多个解决scheme已经发布,工作很好! 但是,为了防止任何人需要其他的东西,我想我会发布两个解决scheme,我个人用在seleniumC#来testing是否存在一个元素! 希望它有帮助,欢呼!
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; } }
这是第二个
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; } }
这是我的解决scheme,你不想等到元素改变之前。 在这个代码中,webdriver等待2秒钟,然后继续。
WebDriverWait等待=新的WebDriverWait(驱动程序,TimeSpan.FromMilliseconds(2000)); wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name( “HTML-名”)));
试试这个代码:
New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed)
正在寻找如何在Selenium等待条件,降落在这个线程,这里是我现在使用的:
WebDriverWait wait = new WebDriverWait(m_driver, TimeSpan.FromSeconds(10)); wait.Until(d => ReadCell(row, col) != "");
ReadCell(row, col) != ""
可以是任何条件。 像这样,因为:
- 这是我的
- 允许内联
new WebDriverWait(driver, TimeSpan.FromSeconds(10)). Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));
第一个答案是好的,我的问题是, 未处理的exception没有正确closuresnetworking驱动程序,并保持了我曾经使用的第一个值是1秒。
如果你得到同样的问题
restart you visual studio
并确保all the exceptions are handled
正确。