我想确保在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"));
我主要是挣扎如何设置匿名功能…
当前回答
使用c#扩展方法:我们可以解决等待直到元素可见的问题。 一个特定元素的最大reties是100。
public static bool WaitForElementToBeVisible(IWebDriver browser, By by)
{
int attemptToFindElement = 0;
bool elementFound = false;
IWebElement elementIdentifier = null;
do
{
attemptToFindElement++;
try
{
elementIdentifier = browser.FindWebElement(by);
elementFound = (elementIdentifier.Displayed && elementIdentifier.Enabled) ? true : false;
}
catch (Exception)
{
elementFound = false;
}
}
while (elementFound == false && attemptToFindElement < 100);
return elementFound;
}
其他回答
使用Mike Kwan提供的解决方案可能会对整体测试性能产生影响,因为隐式等待将在所有FindElement调用中使用。
很多时候,您希望FindElement在一个元素不存在时立即失败(您正在测试一个畸形的页面、缺失的元素等)。使用隐式等待,这些操作将在抛出异常之前等待整个超时到期。默认的隐式等待设置为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);
}
}
我没有缓存WebDriverWait对象,因为它的创建非常便宜,这个扩展可以同时用于不同的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();
受Loudenvier的解决方案的启发,这里有一个扩展方法,它适用于所有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();
您不希望在元素更改之前等待太长时间。在这段代码中,webdriver在继续之前最多等待2秒。
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(2000)); wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name("html-name")));
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).
Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));
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(导入expected_conditions)中,您还可以选择其他条件。 试试这个:预期条件支持