2013-12-11 226 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的搜索。

相關問題