【问题标题】:Check if a WebElement is stale without handling an exception检查 WebElement 是否过时而不处理异常
【发布时间】:2014-08-20 23:01:13
【问题描述】:

我目前正在通过执行以下操作来检查 WebElement 是否过时:

public static boolean isStale(WebElement element) {
    try {
        element.click();
        return false;
    } catch (StaleElementReferenceException sere) {
        return true;
    }
}

这与为这个问题提供的解决方案相同:

Check for a stale element using selenium 2?

但是,这对我来说似乎相当混乱。有没有一种更简洁的方法可以检查元素是否过时,而无需抛出和捕获异常?

(另外,如果我必须坚持抛出和捕获异常,有没有比单击/发送键/悬停抛出所述异常更好的方法?我可能有一个我没有的 WebElement想要执行任何这些操作,因为它可能会无意中影响其他事情。)

【问题讨论】:

  • 您可以在网络元素上使用getLocation 或任何其他getter,而不是点击。请注意,某些 getter 可能无法连接到 Web 驱动程序,因此可能不会抛出 StaleElementReferenceException

标签: selenium selenium-webdriver


【解决方案1】:

C# 检查网页元素是否过期的经典语句

protected bool IsStale
{
    get { return ExpectedConditions.StalenessOf(webElement)(WebDriver); }
}

【讨论】:

    【解决方案2】:

    我知道这已经有一个公认的答案,我不知道您如何使用过时检查的更大背景,但也许这会对您或其他人有所帮助。您可以让ExpectedConditions.stalenessOf(WebElement) 为您完成工作。例如,

    WebElement pageElement = driver.findElement(By.id("someId"));
    WebDriverWait wait = new WebDriverWait(webDriver, 10);
    // do something that changes state of pageElement
    wait.until(ExpectedConditions.stalenessOf(pageElement));
    

    在这种情况下,您不必做pageElement.click()等来触发检查。

    从文档中,.stalenessOf() 一直等到元素不再附加到 DOM。

    参考:ExpectedConditions

    【讨论】:

    • 为什么element.click会受到驱动程序隐式等待的影响?
    • @richmondwang OP 使用.click() 来测试元素是否存在,如果不存在则捕获异常。使用我上面展示的方法,我们以另一种方式检查陈旧性,因此不再需要 .click()
    • 好吧,假设没有.click(),但是webelement的其他方法仍然受到驱动程序的implicitWait的影响(根据我所做的一些测试和调试)。 ExpectedConditions.stalenessOf(pageElement) 在下面使用.isDisplayed()(如果我没记错的话),因此这也会等待超时,然后才会(说它已经过时)抛出StaleElementReferenceException。我想知道如果它们已经过时,为什么它们会受到implicitWait 的影响?
    • 因为如果你依靠一个元素的陈旧性来继续你的测试,在大范围内这会因为隐式等待而非常缓慢,所以我想知道。不过,我所做的是创建了一个采用匿名函数的方法。在方法内部,我关闭了implicitWait,运行anon函数,然后再次开启implicitWait。你怎么看?还有其他更优雅、更高效的方法吗?
    • 文档声明你不应该混合隐式和显式等待......你会得到意想不到的结果。这可能就是你所看到的。 ExpectedConditions 每 500 毫秒轮询一次(默认情况下),所以它非常快......你不应该因为等待陈旧而看到任何缓慢。
    【解决方案3】:

    Webdriver 本身也使用 try/catch 构造来检查陈旧性。

    来自 org.openqa.selenium.support.ui.ExpectedConditions.java:

      public static ExpectedCondition<Boolean> stalenessOf(final WebElement element) {
        return new ExpectedCondition<Boolean>() {
          @Override
          public Boolean apply(WebDriver ignored) {
            try {
              // Calling any method forces a staleness check
              element.isEnabled();
              return false;
            } catch (StaleElementReferenceException expected) {
              return true;
            }
          }
    
          @Override
          public String toString() {
            return String.format("element (%s) to become stale", element);
          }
        };
    }
    

    isEnabled() 检查比使用单击操作更好 - 单击元素可能会导致不需要的副作用,而您只想检查元素的状态。

    【讨论】:

      【解决方案4】:

      我不完全明白你想要做什么。您所说的“混乱”解决方案是什么意思?

      也许您可以结合not 使用显式等待条件stalenessOf。 但在我看来,每个解决方案似乎都不稳定。

      我所做的是,我在一个助手类中有一个点击例程,这个想法是这样的:

      public void ClickHelper(WebDriver driver, By by){
          int counter = 1;
          int max = 5;
          while (counter <= max) {
             try {
                  WebElement clickableWebElement = driver.findElement(by);
                  clickableWebElement.click();
                  return;
                  } catch (StaleElementReferenceException e) {
                      System.out.print("\nTry " + counter + " with StaleElementReferenceException:\n" + e.getMessage() + "\n");
                  }
             versuche++;
          }
          throw new RuntimeException("We tried " + max + " times, but there is still an Exception. Check Log!");
      }
      

      小心,我只是简单地输入了我自己的方法(还有一些检查,我个人使用 xpath 而不是通过 etc)。可能有一些拼写错误,但我想你会理解基本思想。由于我使用了这个 Helpermethode,我不必关心 webelements 的陈旧性。您可以更改最大值,但我个人认为,如果网站如此不稳定,元素太陈旧,我会与开发人员交谈,因为这不是一个好的网站。

      【讨论】:

      【解决方案5】:

      这应该可以在不依赖显示/启用的情况下工作:

      def is_element_on_page(element):
                  try:
                      element.get_attribute('')
                      return True
                  except StaleElementReferenceException:
                      return False
      

      【讨论】:

        猜你喜欢
        • 2017-02-15
        • 2011-05-14
        • 2016-04-12
        • 2023-04-08
        • 2010-12-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多