【问题标题】:Stale Element Reference error in SeleniumSelenium 中的过时元素引用错误
【发布时间】:2018-01-01 13:53:55
【问题描述】:

我在运行 selenium 测试时遇到错误

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'.

这里是代码

        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);


    }

我浏览了有关此问题的类似帖子,并尝试了其他成员提到的许多解决方案,但不知何故,等待和预期条件似乎不起作用。非常感谢任何其他方向的思考。

这些是我尝试过的选项

  1. 通过 Thread.sleep() 方法增加了等待时间
  2. 引入等待和预期条件

    WebDriverWait 等待 = new WebDriverWait(驱动程序, 150);

    wait.until(预期条件。 presentOfAllElementsLocatedBy(By.className("text-heading")));

【问题讨论】:

标签: java selenium


【解决方案1】:

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

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

为避免这种情况,您需要在从另一个页面使用 .back() 后将元素重新抓取到页面 1 上的 category。一种方法是我在下面写的。页面在每个循环的底部被抓取。

List<WebElement> category = driver.findElements(By.className("a2s-skill-block"));
for (int i = 0; i < category.size(); i++)
{
    category.get(i).click();
    // sleeps are a bad practice, use WebDriverWait instead
    driver.navigate().back();
    driver.findElement(By.id("iApps")).click();
    // sleeps are a bad practice, use WebDriverWait instead
    category = driver.findElements(By.className("a2s-skill-block"));
}

【讨论】:

  • 非常感谢您的帮助!这对我有用,而且我对未来如何解决这些类型的问题有了一个好主意
  • 如果这个或任何其他答案有用,请点赞。找到问题的答案后,请将其标记为已接受,以免问题没有得到解答。
【解决方案2】:

你在 for 循环之前找出页面上的所有类别。当你点击循环里面的东西进入另一个页面时,其实已经触发了'Stale Element Refrence',不管你最终回到了最后一页。

以下条件将触发“过时元素引用”

条件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);

【讨论】:

  • 谢谢,这行得通。详细的解释也很有帮助
猜你喜欢
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-20
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2020-11-13
  • 1970-01-01
相关资源
最近更新 更多