2013-12-11 347 views
2

当前环境上的getText()生成StaleElementReferenceExeption:在Firefox运行硒的webdriver上表元素

  • Selenium服务器版本2.37.0
  • RemoteWebDriver
  • 没有的Ajax /异步加载内容

我的测试正在尝试验证HTML表格的每个单元格的内容。之前访问任何表元素的明确等待验证表一旦被证实存在的<TBODY>元素存在

ExpectedCondition<WebElement> recruitTableIsPresent = ExpectedConditions.presenceOfElementLocated(By.id("newRecruitFieldAgentWidget:newRecruitDataTable_data")); 
new WebDriverWait(driver, 5).until(recruitTableIsPresent); 

,数据是通过行和列拉出

private Stats[] parseStats() { 
    String xpath = "//tbody[@id='regionalFieldAgentWidget:regionalDataTable_data']/tr[%d]/td[%d]"; 
    Stats[] stats = new Stats[3]; 
    for (int i = 0; i < stats.length; i++) { 
     String inProgresOrders = cellContent(xpath, i, 1); 
     String maxCapacity = cellContent(xpath, i, 2); 
     String allocationRatio = cellContent(xpath, i, 3); 
     Stats[i] = new Stats(inProgressORders, maxCapacity, allocationRatio); 
    } 
    return stats; 
} 

private String cellContent(String xpathTemplate, int row, int cell) { 
    String xpath = String.format(xpathTemplate, row + 1, cell + 1); 
    new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath))); 
    WebElement elementByXPath = driver.findElementByXPath(xpath); 
    return elementByXPath.getText(); 
} 

我不查看任何竞态条件,因为表格内容是用页面填充的,而不是在异步调用中。另外,我看到其他答案,建议通过驱动程序实例调用findElement()将刷新缓存。最后,在访问元素之前的明确等待应确保标签存在。

什么引起了gettext()方法返回了以下异常:

org.openqa.selenium.StaleElementReferenceException:元素在缓存中没有发现 - 也许是页面发生了变化,因为它是抬头

值得注意的是,失败是间歇性的。一些执行失败,而其他通过相同的代码通过。导致失败的表格单元格也不一致。

+0

使用try Thread.sleep(1000)调试是否真的是种族问题,否则唯一的问题可能与刷新元素缓存有关! – Anirudh

+0

我以前添加了5秒显式等待,没有直到()条件没有成功。我宁愿避免睡觉的线程,但我会试试 – PaoloV

+1

原来,有一个异步回发,我一开始并没有注意到,这大大简化了问题。正如在类似的问题中提到的,下面的代码片段像一个魅力等待活动异步请求完成:(Long)jsContext.executeScript(“return(window.jQuery || {active:0})。active”); – PaoloV

回答

0

原来我曾经提到过这里有一个竞争条件。由于jQuery通过PrimeFaces可用,所以在其他一些帖子中提到了一个非常方便的解决方案。我采取了以下方法来等待任何异步请求解析页面元素

public static void waitForPageLoad(JavascriptExecutor jsContext) { 
    while (getActiveConnections(jsContext) > 0) { 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException ex) { 
      throw new RuntimeException(ex); 
     } 
    } 
} 

private static long getActiveConnections(JavascriptExecutor jsContext) { 
    return (Long) jsContext.executeScript("return (window.jQuery || { active : 0 }).active"); 
} 

每个内置驱动程序实现实现JavascriptExecutor接口之前返回,所以调用代码非常简单:

WebDriver driver = new FirefoxDriver(); 
waitForPageLoad((JavascriptExecutor) driver); 
0

有一个使用Html-Agility-Pack的解决方案。
只有当您想要读取该页面的数据时才能使用。

这正好喜欢这个

//Convert the pageContent into documentNode. 

void _getHtmlNode(IWebDriver driver){ 
    var htmlDocument = new HtmlDocument(); 
    htmlDocument.LoadHtml(driver.PageSource); 
    return htmlDocument.DocumentNode; 
} 

private Stats[] parseStats(){ 
    String xpath = "//tbody[@id='regionalFieldAgentWidget:regionalDataTable_data']/tr[%d]/td[%d]"; 
    Stats[] stats = new Stats[3]; 
    for (int i = 0; i &lt; stats.Length; i++) { 
     String inProgresOrders = cellContent(xpath, i, 1); 
     String maxCapacity = cellContent(xpath, i, 2); 
     String allocationRatio = cellContent(xpath, i, 3); 
     Stats[i] = new Stats(inProgressORders, maxCapacity, allocationRatio); 
    } 
    return stats; 
} 

private String cellContent(String xpathTemplate, int row, int cell) { 
    String xpath = String.format(xpathTemplate, row + 1, cell + 1); 
    new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath))); 
    var documentNode = _getHtmlNode(driver); 
    var elementByXPath = documentNode.SelectSingleNode(xpath); 
    return elementByXPath.InnerText; 
} 

现在读取任何数据。

使用htmlNode的一些提示。
1. driver.FindElement类似: document.SelectSingleNode
2.类似于driver.FindElements: document.SelectNodes
3. driver.Text类似: document.InnerText。



欲了解更多关于HtmlNode的搜索。

相关问题