Java和Selenium陈旧元素错误

时间:2014-03-04 20:03:49

标签: java selenium

我一直遇到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;

1 个答案:

答案 0 :(得分:2)

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

例如,您可以使用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   IsTrue运算)

     

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

the function returns neither null nor false,
the function throws an unignored exception,
the timeout expires,
the current thread is interrupted

如果你看一下visibilityOfElementLocated

的实现
  /**
   * 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;
      }
    };
  }

它已经忽略了元素的陈旧性(意味着如果元素过时并且轮询继续,它将返回null)并且相同的函数将在找到元素后返回该元素,或者如果上面描述的内容则抛出异常发生。


  

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

您应该使用Page Object设计模型。如果你使用PageFactory启动所有元素,并带来许多其他好处(主要是维护方面),你也会失去大部分陈旧性问题,因为在这种情况下,WebElements会被懒惰地评估,这意味着每次调用该元素时都会执行元素查找。