Stale Element Reference error in Selenium

时间:2018-01-01 02:07:32

标签: java selenium

I am getting an error while running my selenium tests

Exception in thread "main" 
org.openqa.selenium.StaleElementReferenceException: stale element 
reference: element is not attached to the page document
  (Session info: chrome=63.0.3239.84)
  (Driver info: chromedriver=2.34.522932 ( 
4140ab217e1ca1bec0c4b4d1b148f3361eb3a03e),platform=Mac OS X 10.12.6 
x86_64) (WARNING: The server did not provide any stacktrace 
information)
Command duration or timeout: 0 milliseconds
For documentation on this error, please visit: 
 http://seleniumhq.org/exceptions/stale_element_reference.html
01T19:05:14.666Z'.

Here is the code

        List<WebElement> category = 
driver.findElements(By.className("a2s-skill-block"));


for(int i = 0;i<category.size();i++) {

        category.get(i).click();
        Thread.sleep(7000);


        driver.navigate().back();
    //  WebElement skills1 = driver.findElement(By.id("iApps"));
        //skills1.click();
        Thread.sleep(15000);


    }

I went through similar thread posts on this question and tried a lot of solutions mentioned by fellow members but somehow the wait and Expected COnditions don't seem to work.Any other direction of thought is really appreciated.

These are the options I tried

  1. Increased the wait time through Thread.sleep() method
  2. Introduced wait and Expected Conditions

    WebDriverWait wait = new WebDriverWait(driver, 150);

    wait.until(ExpectedConditions. presenceOfAllElementsLocatedBy(By.className("text-heading")));

2 个答案:

答案 0 :(得分:1)

您应该花一些时间阅读并了解StaleElementReferenceException是什么。重要的是要了解导致它的原因以及如何避免它。

在这种情况下,您正在抓取页面并使用第1页的元素加载category。然后单击一些链接,将您带到第2页。此时,{{1}中的所有引用陈旧但是尚未引发异常,因为您尚未访问任何变量。然后使用category返回第1页并尝试使用.back()执行某些操作并获取异常。

为避免这种情况,您需要在从其他页面使用category后将元素重新调整到第1页的category。一种方式是我在下面写的。页面在每个循环的底部被抓取。

.back()

答案 1 :(得分:0)

您可以在循环之前找到页面上的所有类别。当您点击循环内的某些内容进入另一个页面时,实际上是“过时元素参考”#39;已经被触发了,最后你终于回到了最后一页。

以下条件会触发“陈旧元素参考”

条件1

上次进入页面时使用找到的元素,并且您至少离开页面一次(即使您再次返回)。

您可以认为,当您进入页面时,Selenium将为Selenium内部的页面分配一个引用,即使您输入了相同的页面,但Selenium也不知道它们是相同的,因此它将分配一个新的引用。

您只能使用找到的元素,哪个页面引用与您当前页面相同。

条件2

留在页面上(不要离开),但是你的脚本触发了找到的元素的HTML DOM节点更改/重新附加/删除。例如,DOM节点的某些属性已更改,或者DOM节点被删除并再次添加回去,所有这些都不会改变。

因此,找到的元素的DOM节点上的任何更改/移动都将触发“陈旧元素参考”。您可以认为条件1只是改变/移动DOM节点的另一种方式。

要解决您的问题,您应该读出所有类别的属性,这些属性可用于在循环中稍后识别该类别。

下面的代码假设每个类别都有唯一的文字:

List<WebElement> category = 
    driver.findElements(By.className("a2s-skill-block"));

List<String> categoryTexts = new ArrayList<String>();

for(WebElement it: category) {
    categoryTexts.add(it.getText());
}

for(int i = 0;i<category.size();i++) {

    driver.findElement(By.xpath("//*[text()='"+categoryTexts.get(i)+"']")).click();
    Thread.sleep(7000);

    driver.navigate().back();
    Thread.sleep(15000);