Java和Selenium过时元素错误

Java和Selenium过时元素错误,java,selenium,Java,Selenium,我在Selenium中不断遇到过时的元素错误。根据我的研究,当你离开一个页面或者元素被改变时,这个错误就会发生。当我浏览一个web元素列表,试图通过一个值来识别其中一个元素时,我总是遇到这个错误。当我尝试比较名称时,下面的if语句总是失败。有人知道我的问题是什么吗? 在一个更大的问题上,是否有一个很好的修复陈旧元素错误的方法?我在网上看到的只是捕捉错误并再次循环。还有比这更好的方法吗 int attempts = 0; while(attempts < 2){ tr

我在Selenium中不断遇到过时的元素错误。根据我的研究,当你离开一个页面或者元素被改变时,这个错误就会发生。当我浏览一个web元素列表,试图通过一个值来识别其中一个元素时,我总是遇到这个错误。当我尝试比较名称时,下面的if语句总是失败。有人知道我的问题是什么吗? 在一个更大的问题上,是否有一个很好的修复陈旧元素错误的方法?我在网上看到的只是捕捉错误并再次循环。还有比这更好的方法吗

    int attempts = 0;
    while(attempts < 2){
    try{
    java.util.List<WebElement> elements = driver.findElements(By.tagName("span"));
    for(WebElement element: elements){
        if(element.getText().equals(elementName)){
          return element;
        }
    }
    }catch (org.openqa.selenium.StaleElementReferenceException e){
                e.printStackTrace();
    }
        attempts++;
    }
    return null;
int尝试次数=0;
而(尝试次数<2次){
试一试{
java.util.List elements=driver.findElements(按.tagName(“span”));
for(WebElement:elements){
if(element.getText().equals(elementName)){
返回元素;
}
}
}catch(org.openqa.selenium.StaleElementReferenceException e){
e、 printStackTrace();
}
尝试++;
}
返回null;

首先,您应该编写更好的定位器。您所做的是将所有
元素查询到webelements列表中,然后在foreach循环中,您再次在每个元素上触发
findElement
方法,直到您从循环中断,并且在循环内触发
getText
方法。这绝对是过火了。最好编写一个定位器来查询特定的元素,比如
//span[text()=='valueofelementnamevaluate']
,然后使用类并等待元素可用于交互

例如,您可以使用
visibilityOfElementLocated
预期条件,如:

WebElement yourSpanElement = (new WebDriverWait(driver, 60))
  .until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[text() == \"valueOfelementNameVariable\"]")));
WebDriverWait的until函数将轮询DOM,直到ExpectedCondition返回true或超时。更准确地说:

public V until(com.google.common.base.Function (伊斯特鲁)

将此实例的输入值重复应用于给定函数 直到出现以下情况之一:

the function returns neither null nor false,
the function throws an unignored exception,
the timeout expires,
the current thread is interrupted
如果你看一下

/**
*检查页面的DOM上是否存在元素的期望
*而且是可见的。可见性意味着图元不仅显示,而且
*还具有大于0的高度和宽度。
*
*@param定位器用于查找元素
*@找到并可见WebElement后返回该WebElement
*/
公共静态预期条件定位元素的可见性(
最终(由定位器提供){
返回新的ExpectedCondition(){
@凌驾
公共WebElement应用(WebDriver){
试一试{
返回元素ifvisible(findelelement(定位器、驱动程序));
}捕获(StaleElementReferenceException e){
返回null;
}
}
@凌驾
公共字符串toString(){
返回“通过“+定位器定位的元素的可见性”;
}
};
}
它已经忽略了元素的过时性(意味着如果元素过时并且轮询继续,它将返回null),并且一旦找到元素,相同的函数将返回该元素,或者如果发生上述情况,则抛出异常


在一个更大的问题上,是否有一个很好的修复陈旧元素错误的方法


您应该使用设计模型。如果您开始使用所有元素,以及它带来的许多其他好处(主要是在维护方面),您也将失去大多数陈旧性问题,因为在这种情况下,WebElements的评估是惰性的,这意味着每次调用某个元素时都会执行该元素的查找。

我要做的一件事是尽可能避免出现类似于上面所述的情况,即避免父页面发生更改。我的意思是,与其在一个站点中浏览一个链接到另一个链接进行测试,不如在一个新窗口中打开任何可以打开的链接;切换到那个窗口;当您完成后,关闭它并返回到父级。@Ben我认为这是一个错误的建议,因为您的功能测试应该尽可能地模拟用户的行为。你应该真正地处理这个问题,而不是试图找到一种方法来解决它。wait类可以帮助您轻松克服陈旧性问题。@ErkiM在这方面我同意您的观点,但如果您的测试不是为了模仿用户而进行的,我不同意您的观点;例如网页抓取或获取信息。站点导航量越大,出现站点导航或网络相关问题的可能性就越大。我在这篇文章上的意图是显示,即使子页面出现故障,父页面也可以继续存在。@Ben,我的评论确实是关于网站功能测试的。无论如何,当谈到web抓取时,肯定有一些工具在几乎所有方面都超过了
webdriver
,从
curl
wget
开始,再加上
sed
egrep
之类的工具。但总而言之,我的观点是正确的。谢谢你们两位的帮助。我的问题是,我在模式窗口中弹出的配置文件中进行了更改。因此,每次运行测试时,我都会打开模式窗口,进行更改,保存配置文件并关闭模式。然后,我会重新打开并找到复选框或任何它是作出断言,如果它已经改变或没有。正如您可以想象的,这导致了错误。所以我决定在做了更改之后立即进行断言,这就修复了错误。谢谢这是我在这个主题上看到的最好的帖子。谢谢你的深入解释。我非常熟悉VisiblyYoufeelmentLocate,但我在尝试其他东西。在创建/删除元素后,我一直在使用它来验证元素的存在/不存在。我现在可能会像您所说的那样(使用更好的选择器)查找它并捕获错误,而不是在表中查找元素。你有比这更好的建议吗?我不确定我是否理解你的问题,但是
invisibilityOfElementLoca
  /**
   * An expectation for checking that an element is present on the DOM of a page
   * and visible. Visibility means that the element is not only displayed but
   * also has a height and width that is greater than 0.
   *
   * @param locator used to find the element
   * @return the WebElement once it is located and visible
   */
  public static ExpectedCondition<WebElement> visibilityOfElementLocated(
      final By locator) {
    return new ExpectedCondition<WebElement>() {
      @Override
      public WebElement apply(WebDriver driver) {
        try {
          return elementIfVisible(findElement(locator, driver));
        } catch (StaleElementReferenceException e) {
          return null;
        }
      }

      @Override
      public String toString() {
        return "visibility of element located by " + locator;
      }
    };
  }