我正在编写一些Java Webdriver代码来自动化我的应用程序。如何正确检查页面是否已加载?该应用程序还具有一些Ajax调用。
我已经为WebDriver声明了一个隐式等待。
隐式等待
,可以解决大部分问题。document.readyState
。当然,Selenium已经实现了这个。问题在于异步请求、 AJAX,因为您永远无法确定它是否完成。今天的大多数网页都有永久运行并且一直轮询服务器的脚本。隐式等待
和在必要时使用显式等待
+预期条件
。WebDriverWait wait = new WebDriverWait(driver, 10); // you can reuse this one
WebElement elem = driver.findElement(By.id("myInvisibleElement"));
elem.click();
wait.until(ExpectedConditions.visibilityOf(elem));
这是一个简单的代码段,可以直接使用,对我来说完美地工作。
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);
}
我知道这篇文章有点老了。但在从以上所有代码中收集了所有内容后,我做出了一个不错的方法(解决方案),用于处理ajax运行和常规页面。该代码仅适用于C#语言(因为经过一年的折腾后,Selenium绝对是最佳选择之一)。
该方法被用作扩展方法,也就是说,简单来说,您可以在对象IWebDriver中添加更多功能(方法)。重要的是,您必须在参数中定义“this”以利用它。
超时变量是webdriver等待页面响应的秒数。使用'Selenium'和'Selenium.Support.UI'命名空间,可以执行一段返回布尔值的javascript代码,用于检查文档是否已准备好(complete)并且jQuery是否已加载。如果页面没有jQuery,则该方法将引发异常。此异常由错误处理“捕获”。在catch状态下,将仅检查文档的就绪状态,而不检查jQuery。
public static void WaitUntilDocumentIsReady(this IWebDriver driver, int timeoutInSeconds) {
var javaScriptExecutor = driver as IJavaScriptExecutor;
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
try {
Func<IWebDriver, bool> readyCondition = webDriver => (bool)javaScriptExecutor.ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
wait.Until(readyCondition);
} catch(InvalidOperationException) {
wait.Until(wd => javaScriptExecutor.ExecuteScript("return document.readyState").ToString() == "complete");
}
}
$(document).onReady
是一个不错的起点。如果没有使用jQuery,则可以将其放在页面底部的<script>
标签中。wait
语句执行后页面的确切状态。
... All my page content ...
<script> window.TestReady = true; </script></body></html>
// The timespan determines how long to wait for any 'condition' to return a value
// If it is exceeded an exception is thrown.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5.0));
// Set the 'condition' as an anonymous function returning a boolean
wait.Until<Boolean>(delegate(IWebDriver d)
{
// Check if our global variable is initialized by running a little JS
return (Boolean)((IJavaScriptExecutor)d).ExecuteScript("return typeof(window.TestReady) !== 'undefined' && window.TestReady === true");
});
最近,当我处理一个AJAX应用程序/RIA时,我遇到了同样的问题! 我使用了隐式等待,时间大约为90秒。它会等待,直到元素可用...因此,我们可以做些什么来确保页面完全加载呢?
添加一个布尔语句,检查特定元素的条件是否存在并将其分配给一个变量,检查条件是否为真,只有在条件为真时,“执行必要的操作!” ...通过这种方式,我找到了两个等待都可以使用的方法...
例如:
@Before
{ implicit wait statement}
@Test
{
boolean tr1=Driver.findElement(By.xpath("xx")).isEnabled/isDisplayed;
if (tr1==true && ____)//as many conditions, to make sure, the page is loaded
{
//do the necessary set of actions...
driver.findElement(By.xpath("yy")).click();
}
}
希望这可以帮助到你!对我来说,它也处于实施阶段...
以下是我BasePageObject类中关于等待的一些代码:
public void waitForPageLoadAndTitleContains(int timeout, String pageTitle) {
WebDriverWait wait = new WebDriverWait(driver, timeout, 1000);
wait.until(ExpectedConditions.titleContains(pageTitle));
}
public void waitForElementPresence(By locator, int seconds) {
WebDriverWait wait = new WebDriverWait(driver, seconds);
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}
public void jsWaitForPageToLoad(int timeOutInSeconds) {
JavascriptExecutor js = (JavascriptExecutor) driver;
String jsCommand = "return document.readyState";
// Validate readyState before doing any waits
if (js.executeScript(jsCommand).toString().equals("complete")) {
return;
}
for (int i = 0; i < timeOutInSeconds; i++) {
TimeManager.waitInSeconds(3);
if (js.executeScript(jsCommand).toString().equals("complete")) {
break;
}
}
}
/**
* Looks for a visible OR invisible element via the provided locator for up
* to maxWaitTime. Returns as soon as the element is found.
*
* @param byLocator
* @param maxWaitTime - In seconds
* @return
*
*/
public WebElement findElementThatIsPresent(final By byLocator, int maxWaitTime) {
if (driver == null) {
nullDriverNullPointerExeption();
}
FluentWait<WebDriver> wait = new FluentWait<>(driver).withTimeout(maxWaitTime, java.util.concurrent.TimeUnit.SECONDS)
.pollingEvery(200, java.util.concurrent.TimeUnit.MILLISECONDS);
try {
return wait.until((WebDriver webDriver) -> {
List<WebElement> elems = driver.findElements(byLocator);
if (elems.size() > 0) {
return elems.get(0);
} else {
return null;
}
});
} catch (Exception e) {
return null;
}
}
支持的方法:
/**
* Gets locator.
*
* @param fieldName
* @return
*/
public By getBy(String fieldName) {
try {
return new Annotations(this.getClass().getDeclaredField(fieldName)).buildBy();
} catch (NoSuchFieldException e) {
return null;
}
}
WebDriverWait waitForElement = new WebDriverWait(driver, 15);
WebElement element = driver.findElement(By.id("myElement"));
element.click();
wait.until(ExpectedConditions.visibilityOf(element));
public class IFrame1 extends LoadableComponent<IFrame1> {
private RemoteWebDriver driver;
@FindBy(id = "iFrame1TextFieldTestInputControlID" ) public WebElement iFrame1TextFieldInput;
@FindBy(id = "iFrame1TextFieldTestProcessButtonID" ) public WebElement copyButton;
public IFrame1( RemoteWebDriver drv ) {
super();
this.driver = drv;
this.driver.switchTo().defaultContent();
waitTimer(1, 1000);
this.driver.switchTo().frame("BodyFrame1");
LOGGER.info("IFrame1 constructor...");
}
@Override
protected void isLoaded() throws Error {
LOGGER.info("IFrame1.isLoaded()...");
PageFactory.initElements( driver, this );
try {
assertTrue( "Page visible title is not yet available.",
driver.findElementByCssSelector("body form#webDriverUnitiFrame1TestFormID h1")
.getText().equals("iFrame1 Test") );
} catch ( NoSuchElementException e) {
LOGGER.info("No such element." );
assertTrue("No such element.", false);
}
}
/**
* Method: load
* Overidden method from the LoadableComponent class.
* @return void
* @throws null
*/
@Override
protected void load() {
LOGGER.info("IFrame1.load()...");
Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring( NoSuchElementException.class )
.ignoring( StaleElementReferenceException.class ) ;
wait.until( ExpectedConditions.presenceOfElementLocated(
By.cssSelector("body form#webDriverUnitiFrame1TestFormID h1") ) );
}
....
你可以截屏并将渲染后的页面保存在一个位置,然后检查截屏,以确定页面是否完全加载且没有损坏的图像。
elen
而不是elem
。 - Dawn Drescherdocument.readyState
。 - LetsPlayYahtzee