页面包含一些数据(包含少量行的表)。有“刷新”按钮可以重新加载和重绘页面上的一些元素,而无需重新加载静态数据(ajax)。
我正在尝试为该页面创建正确的测试,但有时会收到StaleElementReferenceException。
我的代码(python):
from selenium import webdriver
browser=webdriver.Firefox()
browser.get('http://mytisite')
browser.implicitly_wait(10)
browser.find_element_by_id('start').click()
while browser.find_element_by_id('status').text!='Done':
browser.find_element_by_id('refresh').click()
for row in browser.find_elements_by_class_name('datarow'):
if not is_correct(row.text):
print "incorrect"
time.sleep(10)
5次迭代中的1次失败就行“如果不是is_correct(row.text)”:
selenium.common.exceptions.StaleElementReferenceException:
Message: u'Element not found in the cache - perhaps the page
has changed since it was looked up' ; Stacktrace: Method
fxdriver.cache.getElementAt threw an error in
resource://fxdriver/modules/web_element_cache.js
主要问题:页面已包含以前的数据,所以我在ajax刷新和webdriver的find_elements_by_class_name('datarow')
元素查询之间进行竞争。
如何正确解决ajax refresh和webdriver之间的竞争?感谢。
答案 0 :(得分:4)
我很害怕,我无法帮助你进行python绑定。但是我可以帮助你提供有关WebDriver的一般建议和一些可能帮助你(其他人)找到他们的python等价物的Java片段。在Selenium中你可以做很多事情来处理AJAX。
<强> 1。隐式等待 - 这将告诉Web驱动程序在一段时间内轮询DOM。
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
<强> 2。显式等待 - 我更喜欢这些!可以将这些与隐式等待结合使用。您可以告诉WebDriver等待某些条件。您需要使用WebDriverWait来使用显式等待。
WebDriverWait wait = new WebDriverWait(driver, 60/*timeout in seconds*/);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("refresh")));
ExpectedConditions
免费提供许多等待条件,我发现它非常有用。
如果我用Java编写上面的代码片段,我会在下面做。注意我在编辑器中写了这个,所以它应该编译。我想这会让你对WebDriverWait的使用有所了解。
WebDriverWait wait = new WebDriverWait(driver, 60/*timeout in seconds*/);
ExpectedCondition<Boolean> untilIFindStatus = ExpectedConditions
.elementToBeSelected(By.id("status"));
while (wait.until(untilIFindStatus)) {
WebElement refresh = wait.until(ExpectedConditions
.elementToBeClickable(By.id("refresh")));
refresh.click();
List<WebElement> allRows = wait.until(ExpectedConditions
.presenceOfAllElementsLocatedBy(By.className("datarow")));
for (WebElement row : allRows) {
if (row.getText().equals("awesome"))
System.out.println("do something");
}
}
最后,根据我的经验,许多现代AJAX应用程序都使用jQuery。我成功地使用了几年的jQuery.active标志来检查页面是否已加载。您可以将其与普通javascript document.readyState
结合使用。这是我在每次“点击”我的AJAX应用程序后等待的一般方法。
ExpectedCondition<Boolean> jQueryActive_toBeZero = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
try {
return ((Long) jsExecutor
.executeScript("return jQuery.active") == 0) ? true
: false;
} catch (WebDriverException e) {
log.debug("It looks like jQuery is not available on the page, skipping the jQuery wait, check stack trace for details");
return true; //skip the wait
}
}
};
ExpectedCondition<Boolean> document_readyState_toBeComplete = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return jsExecutor.executeScript("return document.readyState")
.toString().equals("complete") ? true : false;
}
};
wait.until(jQueryActive_toBeZero);
wait.until(document_readyState_toBeComplete);
答案 1 :(得分:3)
在两种情况之一中引发陈旧元素引用异常,第一种情况比第二种情况更常见:
请仔细阅读以下selenium文档以获取更多信息