【问题标题】:StaleElementReferenceException when trying to reidentify the object尝试重新识别对象时出现 StaleElementReferenceException
【发布时间】:2014-08-05 19:04:19
【问题描述】:

当我前进并返回父页面时,我遇到了识别对象的问题。

这里是场景。我想点击主页中的每个链接并打印页面标题并返回主页。

以下是我尝试过的代码。单击第一个链接并返回主页可以正常工作。此时,需要识别列表对象,不包括已访问的链接。怎么做?

在 QTP 中,我们有 RefreshObject 和 Init 来执行此操作。 WebDriver中是否有类似的方法?

WebDriver driver = new FirefoxDriver();
driver.get("http://www.googl.com/");
driver.manage().window().maximize();

List<WebElement> objWEs = driver.findElements(By.tagName("a"));
for(WebElement e:objWEs)
{
    if(!e.getText().isEmpty())
    {
        e.click();
        System.out.println(driver.getTitle());
        driver.navigate().back();
    }
}
driver.close();

【问题讨论】:

    标签: selenium selenium-webdriver


    【解决方案1】:

    一旦您导航到另一个网页,甚至切换到同一网页中的iframe,您在内存中的任何WebElement 对象都可能“过时”。

    一个可选的解决方案是列出所有元素 ID,然后迭代该列表:

    Set<String> linkIds = new HashSet<String>();
    List<WebElement> links = driver.findElements(By.tagName("a"));
    for (WebElement link : links)
    {
        if(!link.getText().isEmpty())
            linkIds.add(link.getAttribute("id"));
    }
    for (String linkId : linkIds)
    {
        driver.findElement(By.id(linkId)).click();
        System.out.println(driver.getTitle());
        driver.navigate().back();
    }
    

    但请注意,以上所有内容均假设每个链接都有一个唯一的 ID,并且当您导航返回该网页时,所有链接仍保留在该网页中。如果您正在访问的特定网页不是这种情况,那么这里需要一种替代方法。

    您可以迭代链接索引,而不是迭代链接 ID,假设当您导航进出网页时链接保持相同的顺序。不过这样的效率有点低,因为您必须在每次迭代开始时检索所有链接的整个列表。

    for (int i=0; true; i++)
    {
        List<WebElement> links = driver.findElements(By.tagName("a"));
        if (i >= links.size())
            break;
        links.get(i).click();
        System.out.println(driver.getTitle());
        driver.navigate().back();
    }
    

    当您导航回网页时,即使链接的顺序不同,上述代码也应该可以正常工作。但是,在这种情况下,您很可能会错过其中的一些。

    【讨论】:

    • 对于您的第一种方法,我可以将所有列表值复制到另一个对象中并按索引检索并执行操作吗?你能帮我把这个 WebElements 列表复制到另一个列表吗?
    • @Uday:这正是我在第一种方法中所做的。 linkIds 对象包含所有值,而不是按索引检索这些值,我使用 for (String linkId : linkIds) 迭代它们。
    • 我理解你的逻辑,但你需要依赖 ID。所以我的想法是复制对象。并按索引检索。通过这种方式,您无需依赖任何其他属性/属性。我有道理还是我想得太愚蠢(仅供参考......我对Java很陌生)?
    • @Uday:正如我在答案顶部提到的,一旦您导航到另一个网页,您就不能再依赖导航之前内存中的任何 WebElement 对象.没有办法“存储”WebElement 对象,这就是为什么您必须在返回原始网页后再次“找到”它们。为此,您需要使用其中一个属性,在导航之前 CAN 将其保存(例如,在字符串数组中)。
    • 是的,知道了,但我的问题仍然存在,因为没有唯一标识符。如本例所示,我该怎么做?没有 id 字段,并且并非所有链接都需要类。所以尝试用文本捕获,但限制是不应该存在相同的链接名称。这是正确的吗? if(!link.getText().isEmpty()) linkIds.add(link.getAttribute("text"));
    【解决方案2】:

    这是我上述问题的完整代码。

            WebDriver driver = new FirefoxDriver();
            driver.manage().timeouts().implicitlyWait(1, TimeUnit.MINUTES);
            driver.get("http://www.googl.com/");
            driver.manage().window().maximize();
    
            for (int i=0; true; i++)
            {
                List<WebElement> links = driver.findElements(By.tagName("a"));
                if (i >= links.size())
                    break;
                WebElement ele=links.get(i);
                if(!ele.getText().isEmpty())
                {
                    ele.click();
                    System.out.println(driver.getTitle());
                    driver.navigate().back();
                }
            }
    
            driver.close();
    

    【讨论】:

      猜你喜欢
      • 2017-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多