我正致力于自动化一个网站,该网站有许多通过JS事件加载新网页的链接。基本上,有些元素是可点击的,点击一个元素会导致一些JavaScript运行,这会导致表单被提交并路由到新页面。
现在,如果这些只是标准的HTML链接,那就没有问题了,因为Selenium非常聪明,可以告诉他们有一个新页面即将来临并等待做事。但是,尽管如此,Selenium无法分辨出这个实例中的点击是否会导致新页面加载,因此它不会等待并且继续前进。因此它不会等待新页面,尝试查找不存在的元素,我的测试都会失败。长号。
作为临时解决方案,我只是将程序暂停三秒钟,如下:
oldPageDriver.clickThatButton();
try {
Thread.sleep(3000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
newPageDriver = new NewPageDriver(driver);
newPageDriver.doStuffOnNewPage();
这样可行。我不喜欢它,因为它是“hacky”,只是打断程序而不是做一些更聪明的事情。因为延迟是在三秒钟硬编码,所以如果链接工作但是速度慢,我会失败。我已经考虑过类似于隐式等待的东西,但它完成了同样的事情,并且在经过大量研究后,我在Java中找不到一个可靠,可行的答案。
那么,任何人都可以提出解决方法吗?具体来说,如何让Selenium知道一个新的页面,并等到它可用?
答案 0 :(得分:6)
等待document.ready事件并不是解决此问题的全部方法,因为此代码仍然处于竞争状态:有时在处理click事件之前触发此代码,因此直接返回,因为浏览器没有& #39; t开始加载新页面。
经过一番搜索后,我在Obay the testing goat找到了一个帖子,该帖子有解决此问题的方法。该解决方案的c#代码如下:
IWebElement page = null;
...
public void WaitForPageLoad()
{
if (page != null)
{
var waitForCurrentPageToStale = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForCurrentPageToStale.Until(ExpectedConditions.StalenessOf(page));
}
var waitForDocumentReady = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForDocumentReady.Until((wdriver) => (driver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));
page = driver.FindElement(By.TagName("html"));
}
` 我在driver.navigate.gotourl之后直接触发此方法,以便它尽快获得页面的引用。玩得开心!
答案 1 :(得分:3)
显式等待是您所需要的;
http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp
您可以直接将其添加到测试中,或者您可能想要将其干掉,特别是如果存在共同的等待期望,例如旋转图标消失。
您可以将click方法扩展为在单击或后续页面对象后始终等待,将wait_until_loaded方法添加到基页类。还有许多其他有效的方法,但取决于AUT的实现方式
答案 2 :(得分:3)
简单的 ready2use 代码段,非常适合我
static void waitForPageLoad(WebDriver wdriver) {
WebDriverWait wait = new WebDriverWait(wdriver, 60);
Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {
@Override
public boolean apply(WebDriver input) {
return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
}
};
wait.until(pageLoaded);
}