我想确保在webdriver开始做事情之前,一个元素是存在的。
我正在尝试这样做:
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, 5));
wait.Until(By.Id("login"));
我主要是挣扎如何设置匿名功能…
我想确保在webdriver开始做事情之前,一个元素是存在的。
我正在尝试这样做:
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, 5));
wait.Until(By.Id("login"));
我主要是挣扎如何设置匿名功能…
当前回答
您不希望在元素更改之前等待太长时间。在这段代码中,webdriver在继续之前最多等待2秒。
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(2000)); wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name("html-name")));
其他回答
我混淆了匿名函数和谓词。这里有一个小帮手方法:
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)));
}
您不希望在元素更改之前等待太长时间。在这段代码中,webdriver在继续之前最多等待2秒。
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(2000)); wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name("html-name")));
你也可以使用隐式等待:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
隐式等待是告诉WebDriver轮询DOM 在试图找到一个或多个元素时的时间 暂时不可用。默认设置为0。设置好后, 为WebDriver对象实例的生命周期设置隐式等待。
因为我使用一个已经找到的IWebElement来分离页面元素定义和页面测试场景,所以可以这样做:
public static void WaitForElementToBecomeVisibleWithinTimeout(IWebDriver driver, IWebElement element, int timeout)
{
new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until(ElementIsVisible(element));
}
private static Func<IWebDriver, bool> ElementIsVisible(IWebElement element)
{
return driver => {
try
{
return element.Displayed;
}
catch(Exception)
{
// If element is null, stale or if it cannot be located
return false;
}
};
}
使用Rn222的答案和akns1的答案来使用ISearchContext,返回单个元素或列表。并且可以指定元素的最小数量:
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);
}
}
使用示例:
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();