【问题标题】:Waiting for Element to become stale, why doesn't 'ExpectedConditions.stalenessOf' work?等待元素变得陈旧,为什么'ExpectedConditions.stalenessOf'不起作用?
【发布时间】:2017-06-26 09:41:54
【问题描述】:

我创建了以下方法:

public void waitAndClickElement(WebElement element) throws InterruptedException {
    try {
        Boolean elementPresent = this.wait.until(ExpectedConditions.elementToBeClickable(element)).isEnabled();
        if (elementPresent == true && element.isDisplayed()) {
            element.click();
            System.out.println("Clicked on the element: " + element.getText());
        }
    } catch (StaleElementReferenceException elementUpdated) {
        Boolean elementPresent = wait.until(ExpectedConditions.stalenessOf(element));
        if (elementPresent == true) {
            WebElement staleElement = element;
            staleElement.click();
            System.out.println("Clicked on the 'Stale' element: " + element.getText());
        }
    } catch (NoSuchElementException e) {
        System.out.println("Exception! - Could not click on the element: " + element.getText() + ", Exception: "+ e.toString());
        throw (e);
    } finally {
    }
}

但我似乎仍然得到以下异常:

预期条件失败:等待元素(Proxy element for: DefaultElementLocator 'By.xpath: //a[text()='Exchange Now »']')变得陈旧(使用 500 尝试了 20 秒)毫秒间隔)

但是,假设 20 个构建中有 18 个可以使用相同的方法,有什么想法吗?

谢谢你的帮助

【问题讨论】:

  • 不要在catch (StaleElementReferenceException) 块中使用所有逻辑,为什么不再次调用waitAndClickElement(element)?虽然这取决于您如何创建WebElement,但如果您使用缓存查找,它总是会过时,但如果您使用的方法在使用时会被发现,例如FindBy's ,它会一直尝试点击,直到它不再过期。

标签: java selenium selenium-webdriver webdriver


【解决方案1】:

如果您将站点更改为另一个 driver.get("http://completely.different.site.com/");,则此元素将过时(不再存在于 DOM 中)。陈旧意味着 DOM 中的元素不可访问。

【讨论】:

  • 谢谢,但我的大部分测试执行都通过了相同的测试,它只是偶尔会出现此错误,例如 3 次构建将失败,共 20 次。
  • 陈旧元素永远不会出现。所以这里有问题:Boolean elementPresent = wait.until(ExpectedConditions.stalenessOf(element));,这取决于你想要做什么。
  • 这很奇怪,因为即使使用列出的方法,元素似乎仍然过时
  • 我宁愿像this 那样使用try-catch 循环。还是不清楚,你想达到什么。
  • 感谢@Grzegorz Górkiewicz 我需要知道为什么当点击预期元素时,我的代码似乎只在少数测试用例上失败,而对所有测试用例使用相同的方法
【解决方案2】:

您的问题的直接答案是您正在等待一个已经过时的元素变得过时。我不确定你的意图是什么。

您的函数过于复杂,不会像您想象的那样工作。

如果一个元素是可点击的,它也会被启用和显示,所以你不需要检查所有三个。如果元素抛出 StaleElementReferenceException,它不会变得“过时”。

我建议你用下面的替换你当前的函数。

public void waitAndClickElement(By locator)
{
    try
    {
        this.wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
    }
    catch (TimeoutException e)
    {
        System.out.println("Count not click element <" + locator.toString() + ">");
    }
}

传递定位器而不是元素而不是元素本身,这将简化很多事情。如果元素存在并且可点击,它将被点击。如果它不存在或永远无法点击,它会抛出一个TimeoutException,你可以抓住它。

另外,写element.toString() 会为元素写一些ID,这不会是人类可读或有意义的。你最好写 locator.toString() 它将返回定位器的类型,例如By.cssSelector: #hplogo.

【讨论】:

  • 再次感谢您的帮助,您认为我应该添加额外的预防措施并尝试再次单击对象吗?
  • 没有。我会等你认为有必要的时间。等待两次不会完成任何事情。例如,等待一次 30s 与等待两次 15s 是一样的。它只是更有意义,更清晰,并且等待 30 秒的代码更少。
  • 再次感谢您的帮助,在 try 和 catch 块中使用 'Exception e' 会更好吗?
  • 或使用:Throwable?
  • 最佳实践是只捕获您想要处理的内容。在这种情况下,我只会处理TimeoutException,因为这是我所期望的。这实际上取决于您想对可能在此处捕获的其他异常执行什么操作。
猜你喜欢
  • 1970-01-01
  • 2018-04-08
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 2019-10-21
  • 2013-05-14
  • 2022-11-10
  • 1970-01-01
相关资源
最近更新 更多