听起来像显式等待可能是您需要的。类中有一组即用型条件ExpectedConditions
(有关更多信息,请参见https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp)。但是一旦你了解了它们的工作原理,制作你自己的就很简单了。这些的美妙之处在于,与 Thread.sleep() 不同,一旦满足条件,它将立即停止等待。
我写了一些我过去用于等待“页面加载”的具体示例,然后稍微了解如何制作自己的示例,以防万一它对您有用:
如果您的页面很少使用 ajax 内容,并且加载了一些静态内容一次,您可以实现显式等待条件来检查 DOM 的 readyState 属性
// this could benefit being static so it doesn't create new classpath defs every invocation
public ExpectedCondition<Boolean> readyStateIsComplete() {
return new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver webDriver) {
String readyState = (String) ((JavascriptExecutor) webDriver)
.executeScript("return document.readyState");
return readyState.equals("complete");
}
public String toString() {
return "page document's readyState flag to be complete";
}
};
}
只有在所有静态内容完成加载后,此属性才是“完整的”。使用它可能像:
// prepare me like this
WebDriverWait wait = new WebDriverWait(driver, maxSecondsToWait);
// Use me like this
wait.until(readyStateIsComplete());
上面的示例适用于您在所有内容完成之前第一次加载页面。如果您的页面在 ajax 内容上很重,也许您可以尝试等待 ajax 队列达到零,这可以在已经加载的具有 ajax 工作的页面上完成。
public ExpectedCondition<Boolean> activeQueuesToFinish() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
// This is just a formatted javascript block with in-string indenting
String jScript = "if (A4J.AJAX) {" +
" with (A4J.AJAX) {" +
" var queues = A4J.AJAX.EventQueue.getQueues();" +
" for (var queueNames in queues) {" +
" return A4J.AJAX.EventQueue.getQueue(queueNames).getSize() <= 0;" +
" }" +
" }" +
" }" +
" return true;";
try {
return (Boolean) ((JavascriptExecutor) driver).executeScript(jScript);
} catch (WebDriverException e) {
return true;
}
}
public String toString() {
return "active queues to finish.";
}
};
如果你使用 jquery,你可以试试这个来让当前的 ajax 工作完成:
public ExpectedCondition<Boolean> allAjaxRequestsFinish() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
try {
return (Boolean) ((JavascriptExecutor) driver).executeScript("return jQuery.active == 0");
} catch (Exception e) {
return true;
}
}
public String toString() {
return "all ajax requests to finish.";
}
};
}
所有这些条件或您在此模板中创建的任何条件都可以以相同的方式用于动态等待:
wait.until(activeQueuesToFinish());
wait.until(allAjaxRequestsFinish());
编辑:
我的意思是“模板”是具有这种形式的功能:
public ExpectedCondition<Boolean> myCustomCondition(/* some arguments from the outside */) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
// Check something on the page and return either true or false,
// this method will be run repeatedly until either the time
// limit is exceeded, or true is returned
}
public String toString() {
return "a description of what this is waiting for";
}
};
}
这是一个示例,说明如何执行此操作以等待可能会阻碍您的页面的特定元素:
public ExpectedCondition<Boolean> waitForElementToHaveText(final WebElement element, final String expectedText) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
try {
return element.getText().equals(expectedText);
} catch (Exception e) {
return false; // catchall fail case
}
}
public String toString() {
return "an element to have specific text";
}
};
}