我遇到了一个问题。我的网页有DropDownList
控件。一旦DropDownList
值更改(通过选择不同的值),页面将刷新并呈现内容。
然后我必须先使用Thread.Sleep(2000);
并FindElement
。
我的问题:等待页面加载的最佳方式是什么?
我的代码中有很多Thread.Sleep(2000)
的实例,我开始认为这不是解决问题的最佳方法。
这是我的代码:
[TestInitialize()]
public void Setup()
{
if (BaseIntegrationTest.browserType.Equals(BaseIntegrationTest.IE))
{
driver = new InternetExplorerDriver();
}
else if (BaseIntegrationTest.browserType.Equals(BaseIntegrationTest.CHROME))
{
//driver = new ChromeDriver();
}
else if (BaseIntegrationTest.browserType.Equals(BaseIntegrationTest.FIREFOX))
{
driver = new FirefoxDriver();
}
}
第二部分:
[TestMethod]
public void testVerifyData()
{
// ...................
// ...................
driver.FindElement(By.XPath("//*[@id='ctl00_NavigationControl1_lnke']")).Click();
Thread.Sleep(2000);
//select from the dropdownlist.
IWebElement catagory = driver.FindElement(By.Id("ctl00_ContentPlaceHolder1_Filter"));
SelectElement selectCatagory = new SelectElement(catagory);
selectCatagory.SelectByText("Employee");
Thread.Sleep(2000);
// ...................
// ...................
}
答案 0 :(得分:7)
Thread.Sleep()是一种非常沮丧的实现等待的方式
此代码在selenium文档http://seleniumhq.org/docs/04_webdriver_advanced.html
中列出WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement category = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("ctl00_ContentPlaceHolder1_Filter"));
});
这是一个显式等待的示例,其中selenium在找到元素之前不会执行任何操作
隐式等待的一个例子是:
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
IWebElement category = driver.FindElement(By.Id("ctl00_ContentPlaceHolder1_Filter"));
在隐式等待中,驱动程序将等待给定的时间并轮询DOM以查找不存在的任何元素。
修改的
public WaitForElement(string el_id)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement category = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id(el_id));
});
}
答案 1 :(得分:1)
我也通过使用WebDriverWait解决了这个问题。
但我设置等到显示的最后一个元素(例如:页脚,列表中的最后一项)。
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => d.FindElement(By.Id("footer")).Displayed);
或
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => d.FindElements(By.TagName("li")).Last().Displayed);
答案 2 :(得分:1)
在某些情况下,您确实需要等待,在这种情况下,Task.Delay方法将提供比Thread.Sleep更可预测的结果
Task.Delay(1000).Wait(); //等一下
答案 3 :(得分:0)
假设交互引起的刷新是Selenium可以检测到的,那么以下方法可能会满足您的需求:
据我所知,此方法检查浏览器中的状态以查看浏览器是否认为它正在加载某些内容,并等待直到清除此状态。但是,这种就绪状态有点陈旧 - 有很多方法可以动态加载页面或页面的一部分,而就绪状态并不总是准确描述正在发生的事情。
如果您知道由于您的操作会发生什么变化 - 也就是说,如果您知道在与下拉列表进行交互后,将出现之前未在页面上的特定UI元素 - 那么您会最好等待那些特定的UI元素出现。您可以通过编写重复检查isTextPresent并以小增量等待的方法来执行此操作,直到达到超时或出现预期元素。还有其他“是X Present”方法可以在这些方法中使用,您可以在我链接到的Selenium接口的其他地方找到这些方法。
答案 4 :(得分:0)
如果你想在页面加载或超时到期后获得html:
using (var chromeDriver = new ChromeDriver())
{
chromeDriver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(30));
try
{
chromeDriver.Navigate().GoToUrl(link);
return chromeDriver.PageSource;
}
catch (WebDriverTimeoutException)
{
return chromeDriver.PageSource;
}
}
答案 5 :(得分:0)
我为自己制作了一个自定义功能,也许对某人有用:
public static void waitForPageToBeLoaded(WebDriver driver, int time) {
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
};
Wait<WebDriver> wait = new WebDriverWait(driver, Long.valueOf(time));
try {
wait.until(expectation);
} catch(Throwable error) {
System.out.println(error);
mainFunctions.reportFailure("[waitForPageToBeLoaded] Page load took longer than " + time/60 + " min.");
}
} // waitForPageLoaded