如何让Selenium 2.0等待页面加载?
当前回答
我所见过的最好的方法是利用stalenessOf ExpectedCondition,等待旧页面变得陈旧。
例子:
WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));
它将等待十秒钟,让旧的HTML标记变得陈旧,如果没有发生,则抛出异常。
其他回答
对于使用java 8向前的程序员,可以使用下面的代码来使用显式等待等待页面加载。
JavascriptExecutor js = (JavascriptExecutor) driver;
new WebDriverWait(driver, 10).until(webDriver ->
(js).executeScript("return document.readyState;").equals("complete"));
注意:在我上面的代码中使用Lambda表达式,它只在java 8的后续版本中可用。
对于使用低版本Java(即Java 8以下)的程序员,可以使用:
ExpectedCondition<Boolean> cond = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver input) {
JavascriptExecutor js = (JavascriptExecutor) driver;
return js.executeScript("return document.readyState;").equals("complete");
}
};
new WebDriverWait(driver, 100).until(cond);
下面是一个Java 8版本的目前被点赞最多的答案:
WebDriverWait wait = new WebDriverWait(myDriver, Duration.ofSeconds(15));
wait.until(webDriver -> "complete".equals(((JavascriptExecutor) webDriver)
.executeScript("return document.readyState")));
其中myDriver是一个WebDriver对象(前面声明过)。
注意:注意这个方法(document.readyState)只检查DOM。
你可以使用下面的代码片段来加载页面:
IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
或者你可以使用waiter的任何元素被加载,并成为可见/可点击的页面上,最有可能的是,这将是在加载结束时加载,如:
Wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpathOfElement));
var element = GlobalDriver.FindElement(By.XPath(xpathOfElement));
var isSucceededed = element != null;
对于隐式等待,你可以使用如下代码:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)
为了使网页等待一个特定的对象是可见的或某些条件是真实的。您可以使用网页驱动程序等羽。
//120 is maximum number of seconds to wait.
WebDriverWait wait = new WebDriverWait(driver,120);
wait.until(ExpectedConditions.elementToBeClickable("CONDITITON"));
在Java中,另一种选择是让线程在特定的时间内休眠。
Thread.sleep(numberOfSeconds*1000);
//This line will cause thread to sleep for seconds as variable
我创建了一个方法来简化线程。睡眠的方法
public static void wait_time(int seconds){
try {
Thread.sleep(seconds*1000);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
使用wait_time(10)方法;线程将休眠10秒。
所有这些解决方案在特定情况下都是可行的,但它们至少会遇到以下几个问题中的一个:
它们不够通用——它们想让你提前知道,你要访问的页面的某些特定条件将是真的(例如某些元素将被显示)。 它们会出现竞态条件,即您使用的元素实际上同时出现在旧页面和新页面上。
下面是我尝试的避免这个问题的通用解决方案(在Python中):
首先,一个通用的“等待”函数(如果你喜欢,可以使用WebDriverWait,我觉得它们很丑):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
接下来,解决方案依赖于这样一个事实,即selenium为页面上的所有元素记录了一个(内部的)id-number,包括顶级的<html>元素。当页面刷新或加载时,它会获得一个带有新ID的新html元素。
假设你想点击一个文本为“my link”的链接,例如:
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
对于更多python化的、可重用的、通用的helper,你可以创建一个上下文管理器:
from contextlib import contextmanager
@contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
然后你可以在几乎任何硒相互作用中使用它:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
我想那是防弹的!你怎么看?
更多信息在这里关于它的博客文章
推荐文章
- Intellij IDEA Java类在保存时不能自动编译
- 何时使用Mockito.verify()?
- 在maven中安装mvn到底做什么
- 不可变与不可修改的集合
- 如何在JSON中使用杰克逊更改字段名
- GSON -日期格式
- 如何从线程捕获异常
- 无法解析主机"<URL here>"没有与主机名关联的地址
- 如何在Java中打印二叉树图?
- String.format()在Java中格式化双重格式
- com.jcraft.jsch.JSchException: UnknownHostKey
- Java中的操作符重载
- 如何加速gwt编译器?
- 在Hibernate中重新连接分离对象的正确方法是什么?
- 应该……接住环内还是环外?