Selenium WebDriver 如何解决过时的元素引用异常?

Selenium WebDriver How to Resolve Stale Element Reference Exception?

提问人:user1107753 提问时间:4/23/2013 最后编辑:starballuser1107753 更新时间:12/21/2022 访问量:223072

问:

我在 Selenium 2 Web 驱动程序测试中有以下代码,该代码在我调试时有效,但大多数时候当我在构建中运行它时会失败。我知道这一定与页面未刷新的方式有关,但不知道如何解决它,因此任何关于我做错了什么的指示都值得赞赏。我使用 JSF primefaces 作为我的 Web 应用程序框架。当我单击添加新链接时,会出现一个弹出对话框,其中包含一个输入框,我可以在其中输入日期,然后单击保存。正是在获取输入元素以输入文本时,我得到了一个过时的元素 ref 异常。

import static org.junit.Assert.assertEquals;

 import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;


public class EnterActiveSubmissionIntegrationTest {
Map<String, Map<String, String>> tableData = new HashMap<String, Map<String, String>>();

@Test
public void testEnterActiveSubmission() throws Exception {
    // Create a new instance of the Firefox driver
    // Notice that the remainder of the code relies on the interface, 
    // not the implementation.
    System.setProperty("webdriver.chrome.driver", "C:/apps/chromedriver.exe");
    WebDriver driver = new ChromeDriver();

    // And now use this to visit Google
    driver.get("http://localhost:8080/strfingerprinting");
    // Alternatively the same thing can be done like this
    // driver.navigate().to("http://www.google.com");

    // Find the text input element by its name
    WebElement element = driver.findElement(By.linkText("Manage Submissions"));
    element.click();
    parseTableData(driver, "form:submissionDataTable_data", 1);
    assertEquals(tableData.get("form:submissionDataTable_data").get("12"), "Archived");
    
    WebElement newElement = driver.findElement(By.linkText("Add new"));
    newElement.click();
    
    WebDriverWait wait = new WebDriverWait(driver,10);
    wait.until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver driver) {
            WebElement button = driver.findElement(By
                    .name("createForm:dateInput_input"));

            if (button.isDisplayed())
                return true;
            else
                return false;

        }
    });
    
    WebElement textElement = driver.findElement(By.name("createForm:dateInput_input"));
    textElement.sendKeys("24/04/2013");
    WebElement saveElement = driver.findElement(By.name("createForm:saveButton"));
    saveElement.click();
    
    driver.navigate().refresh();
    
    parseTableData(driver, "form:submissionDataTable_data", 2);
    
    //Close the browser
    driver.quit();
}



private void parseTableData(WebDriver driver, String id, int expectedRows) {
    // Check the title of the page or expected element on page
    WebElement subTableElement = driver.findElement(By.id(id));
    List<WebElement> tr_collection=subTableElement.findElements(By.xpath("id('"+ id + "')/tr"));

    assertEquals("incorrect number of rows returned", expectedRows, tr_collection.size());
    int row_num,col_num;
    row_num=1;
    
    if(tableData.get(id) == null) {
        tableData.put(id, new HashMap<String, String>());
    }
    Map<String, String> subTable = tableData.get(id);
    for(WebElement trElement : tr_collection)
    {
        List<WebElement> td_collection=trElement.findElements(By.xpath("td"));
        col_num=1;
        for(WebElement tdElement : td_collection)
        {
            subTable.put(row_num + "" + col_num, tdElement.getText());
            col_num++;
        }
        row_num++;
    }
}
}

当我运行它时,我得到以下异常,但它可能发生在

WebElement textElement = driver.findElement(By.name("createForm:dateInput_input")); 

if (button.isDisplayed())

异常跟踪

org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
(Session info: chrome=26.0.1410.64)
  (Driver info: chromedriver=0.8,platform=Windows NT 6.0 SP2 x86) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 56 milliseconds
For documentation on this error, please visit:        http://seleniumhq.org/exceptions/stale_element_reference.html
Build info: version: '2.32.0', revision: '6c40c187d01409a5dc3b7f8251859150c8af0bcb', time: '2013-04-09 10:39:28'
System info: os.name: 'Windows Vista', os.arch: 'x86', os.version: '6.0', java.version: '1.6.0_10'
Session ID: 784c53b99ad83c44d089fd04e9a42904
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities [{platform=XP, acceptSslCerts=true, javascriptEnabled=true,   browserName=chrome, rotatable=false, driverVersion=0.8, locationContextEnabled=true,  version=26.0.1410.64, cssSelectorsEnabled=true, databaseEnabled=true, handlesAlerts=true,  browserConnectionEnabled=false, nativeEvents=true, webStorageEnabled=true,   applicationCacheEnabled=false, takesScreenshot=true}]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at  sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at  sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:187)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:268)
at org.openqa.selenium.remote.RemoteWebElement.isDisplayed(RemoteWebElement.java:320)
at com.integration.web.EnterActiveSubmissionIntegrationTest$1.apply(EnterActiveSubmissionIntegrationTest.java:58)
at com.integration.web.EnterActiveSubmissionIntegrationTest$1.apply(EnterActiveSubmissionIntegrationTest.java:1)
at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:208)
at com.integration.web.EnterActiveSubmissionIntegrationTest.testEnterActiveSubmission(EnterActiveSubmissionIntegrationTest.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java selenium selenium-webdriver

评论

0赞 user1107753 4/24/2013
谁能就此提出建议?

答:

4赞 Santoshsarma 4/23/2013 #1

StaleElementReferenceException 是由于 findelement 方法访问的元素不可用。

在对元素执行任何操作之前,您需要确保(如果您对该元素的可用性有疑问)

等待元素的可见性

(new WebDriverWait(driver, 10)).until(new ExpectedCondition()
    {
           public Boolean apply(WebDriver d) {
              return d.findElement(By.name("createForm:dateInput_input")).isDisplayed();
     }});

或者,使用逻辑来验证元素是否存在。

评论

0赞 user1107753 4/23/2013
我看不出您添加的代码与我在测试用例中已有的 ode 有什么不同<pre><code> WebDriverWait wait = new WebDriverWait(driver,10);wait.until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { WebElement button = driver.findElement(By .name(“createForm:dateInput_input”)); if (button.isDisplayed()) return true; else return false;</代码></上>
4赞 Ardesco 4/27/2013
等待元素可见性不会阻止您获得 StaleElementException。StaleElementException 是由您已经发现的元素变得过时引起的。
1赞 atott 7/29/2014
我遇到了类似的问题,我已经按照描述决定了这个问题(等待显示)。就我而言,问题是每次在输入的模糊事件上都会显示覆盖层。
70赞 Ardesco 4/27/2013 #2

首先,让我们弄清楚什么是 WebElement。

WebElement 是对 DOM 中元素的引用。

当正在交互的元素被销毁,然后重新创建时,将引发 StaleElementException。如今,大多数复杂的网页都会在用户与它交互时动态移动内容,这需要销毁和重新创建 DOM 中的元素。

发生这种情况时,您以前拥有的对 DOM 中元素的引用将变得过时,并且您不再能够使用此引用与 DOM 中的元素进行交互。发生这种情况时,您将需要刷新您的引用,或者在现实世界中再次查找元素。

评论

0赞 djangofan 10/28/2015
因此,根据该解释的定义,这意味着 Selenium 希望您在遇到此类异常的情况下手动处理重试。右?只要您正在测试的 Web 应用程序是稳定的并且确实可以正确重新加载,那么在 findElement 上重试应该效果很好,并且很可能在第一次重试时。
3赞 Ardesco 10/29/2015
是的。您可以使用显式等待来等待元素变得陈旧,然后再尝试再次查找元素。这里要注意的关键是“你应该知道你的应用程序在做什么”。如果您不知道何时会销毁和重新创建元素,那么您就没有编写自动化测试所需的所有信息。
2赞 Amir Ghahrai 1/4/2016
@Ardesco,所以我假设 PageFactory 和 initElements 在这种情况下不合适,因为对元素的引用是在开始和操作期间创建的,Dom 被销毁并重新创建,引用也被销毁。那么,说 PageFactory 模式不再适合这些类型的现代 Web 应用程序是真的吗?
2赞 Ardesco 1/4/2016
使用 Java PageFactory,您不太可能看到 StaleElementReferenceException。默认情况下,Java PageFactory 类将在您每次尝试使用它时再次查找该元素。该规则的例外情况是,如果使用@CacheLookup注释。在这种情况下,你将看到 StaleElementReference 异常,因为 PageFactory 将使用对元素的缓存引用,而不是再次查找它。
3赞 Ardesco 1/4/2016
如果你很不幸地让一个元素在PageFactory找到该元素,然后用它来做某事之间的几毫秒内,你会得到一个带有java PageFactory的StaleElementReference异常的可能性很小。
25赞 djangofan 6/4/2013 #3

这不是问题。如果将 .findElement 调用包装在 try-catch 块中并捕获 StaleElementReferenceException ,则可以根据需要多次循环并重试,直到成功。

以下是我写的一些例子

Selenide 项目的另一个例子:

public static final Condition hidden = new Condition("hidden", true) {
    @Override
    public boolean apply(WebElement element) {
      try {
        return !element.isDisplayed();
      } catch (StaleElementReferenceException elementHasDisappeared) {
        return true;
      }
    }
  };

评论

10赞 Homewrecker 9/30/2015
这不是一个解决方案,你永远不会想抓住一个 staleElementException。目标是没有。staleElementException 表示您正在执行可以修复的错误操作。
6赞 Jackie 10/28/2015
我并不总是同意在自动更新或复杂的 CSS 转换的情况下怎么办?对于那些人来说,这种方法可能非常有益,在某些情况下可能是必需的。话虽如此,大多数时候你是正确的,使用这种方法应该经过深思熟虑。我认为有一个刷新引用的方法会很好。
2赞 user2440872 7/25/2013 #4

使用 Selenium 提供的预期条件等待 WebElement。

调试时,客户端的速度不如仅运行单元测试或 maven 生成快。 这意味着在调试模式下,客户端有更多时间来准备元素,但如果构建运行相同的代码,则速度要快得多,并且您查找的 WebElement 可能在页面的 DOM 中不可见。

相信我,我遇到了同样的问题。

例如:

inClient.waitUntil(ExpectedConditions.visibilityOf(YourElement,2000))

这个简单的方法在他调用后调用等待 2 秒钟,以显示 DOM 上 WebElement 的可见性。

评论

0赞 djangofan 12/27/2013
这仅适用于设置了 CSS 属性“display”的元素。我想你的意思是建议 ExpectedConditions.isElementPresent ?
1赞 Ardesco 8/26/2015
一个元素可以存在,然后被破坏并再次重新创建,使其过时。
0赞 Curt 8/5/2013 #5

这对我有用(来源在这里):

 /**
     * Attempts to click on an element multiple times (to avoid stale element
     * exceptions caused by rapid DOM refreshes)
     *
     * @param d
     *            The WebDriver
     * @param by
     *            By element locator
     */
    public static void dependableClick(WebDriver d, By by)
    {
        final int MAXIMUM_WAIT_TIME = 10;
        final int MAX_STALE_ELEMENT_RETRIES = 5;

        WebDriverWait wait = new WebDriverWait(d, MAXIMUM_WAIT_TIME);
        int retries = 0;
        while (true)
        {
            try
            {
                wait.until(ExpectedConditions.elementToBeClickable(by)).click();

                return;
            }
            catch (StaleElementReferenceException e)
            {
                if (retries < MAX_STALE_ELEMENT_RETRIES)
                {
                    retries++;
                    continue;
                }
                else
                {
                    throw e;
                }
            }
        }
    }

评论

0赞 djangofan 2/6/2014
通过使用 FluentWait .ignoring 方法,可以使此代码更短。
0赞 Curt 2/6/2014
@djangofan我用我的应用程序尝试过,但没有用。您的里程可能会有所不同。
0赞 djangofan 2/6/2014
这可能是因为您需要将重试循环包装在它周围,而不是在异常中计数。
0赞 Wanping Qu 1/21/2014 #6

WebDriver 必须等到找到 Element 并且超时在 10 秒后。

WebElement myDynamicElement1 = new WebDriverWait(driver, 10).until(
    ExpectedConditions.presenceOfElementLocated(
        By.name("createForm:dateInput_input")
    )
);

评论

0赞 PHPGuru 3/20/2014
您在 ;像这样 ));
9赞 Anurag_user3239660 2/12/2014 #7

尝试等待这样的元素:

// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> stubbornWait = new FluentWait<WebDriver>(driver)
    .withTimeout(30, SECONDS)
    .pollingEvery(5, SECONDS)
    .ignoring(NoSuchElementException.class)
    .ignoring(StaleElementReferenceException.class);

WebElement foo = stubbornWait.until(new Function<WebDriver, WebElement>() {
    public WebElement apply(WebDriver driver) {
        return driver.findElement(By.id("foo"));
    }
});

评论

0赞 Martin Kersten 1/17/2015
很好。。。。我会尽快在我的代码中不配合它。
2赞 Ardesco 9/25/2015
这将帮助您找到在页面最初加载时可能不会呈现的元素,它不会对 StaleElementReferenceException 执行任何操作。
21赞 eeeeaaii 3/19/2014 #8

发生在我身上的是,webdriver 会找到对 DOM 元素的引用,然后在获得该引用后的某个时候,javascript 会删除该元素并重新添加它(因为页面基本上正在重绘)。

试试这个。找出导致 dom 元素从 DOM 中删除的操作。就我而言,这是一个异步 ajax 调用,当 ajax 调用完成时,该元素将从 DOM 中删除。在执行该操作后,立即等待元素过时:

... do a thing, possibly async, that should remove the element from the DOM ...
wait.until(ExpectedConditions.stalenessOf(theElement));

此时,您确定该元素现在已经过时。因此,下次引用该元素时,请再次等待,这次等待它被重新添加到 DOM 中:

wait.until(ExpectedConditions.presenceOfElementLocated(By.id("whatever")))

评论

1赞 Mashton 7/31/2015
谢谢。突出显示使我走上了在测试中处理此异常的道路。ExpectedConditions.StalenessOf
0赞 ericyoung 8/7/2015
@Mashton,你能详细说明你是如何做到的吗?
1赞 Mashton 8/7/2015
我的情况是我有一个“加载更多”按钮,每次都会将结果集合扩展 9(直到所有结果都输入),并且我想要所有结果并检查集合中的特定项目。循环单击按钮直到它不存在,直到我将代码更改为:var element = Driver.FindElements(By.XPath(“MyPath”)) 。FirstOrDefault();if (element != null) 元素。咔嚓();等。直到(ExpectedConditions.StalenessOf(element));循环并重做。
2赞 Ashish Sharda 7/2/2014 #9

我建议不要将 Selenium WebDriver 用于 .@CachelookUpStaleElementReferenceException

如果您使用的是注释并且有 ,只需将其注释掉并检查即可。@FindBy@CacheLookUp

-1赞 Kishor Gaur 4/16/2015 #10

如果我们不确定答案,请不要混淆别人。对于最终用户来说,这是非常令人沮丧的。简单而简短的回答是 在 WebDriver 中使用 @CacheLookup 注释。请参阅以下链接。@CacheLookup如何在 WebDriver 中工作?

评论

2赞 Ardesco 12/23/2015
“@CacheLookup”将导致 StaleElementReferenceExceptions。如果您不想拥有它们,则不应使用@CacheLookup注解。Java Page Factory 可能会遇到争用条件,即您偶尔会在不使用“@CacheLookup”注释的情况下获得 StaleElementReferenceException,因为在后台它会找到一个元素,然后尝试使用它。如果你不走运,元素将在找到元素的那一刻和使用元素的那一刻之间变得陈旧。
1赞 Raghu K Nair 5/6/2015 #11

我已经用下面的代码解决了这个问题。

public WebElement waitForElement(final By findBy, final int waitTime) {
    Wait<AppiumDriver> wait = new FluentWait<>((AppiumDriver) driver)
            .withTimeout(waitTime, TimeUnit.SECONDS)
            .pollingEvery(POLL_TIME, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class,StaleElementReferenceException.class);

    WebElement webElement = wait.until(new Function<AppiumDriver, WebElement>() {
        @Override
        public WebElement apply(AppiumDriver driver) {
            System.out.println("Trying to find element " + findBy.toString());                
            WebElement element = driver.findElement(findBy);
            return element;
        }
    });
    return webElement;
}

评论

1赞 Ardesco 12/23/2015
你不能通过执行'driver.findElement(findBy)'来获得StaleElementReferenceException;,你可以通过重用一个现在已经过时的现有WebElement来得到一个StaleElementReferenceException(见下面的答案)。将“StaleElementReferenceException.class”添加到 .ignoring() 块是过时的代码。
0赞 rajkrish06 9/30/2015 #12

在带有 for 循环的 try catch 块中使用 webdriverwait 和 ExpectedCondition EX:用于 python

for i in range(4):
    try:
        element = WebDriverWait(driver, 120).until( \
                EC.presence_of_element_located((By.XPATH, 'xpath')))
        element.click()    
        break
    except StaleElementReferenceException:
        print "exception "
-1赞 vkrams 3/31/2016 #13

参考 @djangofan 给出的答案,看起来可行的解决方案是将代码保留在可能发生过时的块中。当我使用下面的代码时,我没有遇到任何问题。try catch

public void inputName(String name)
{
    try {
        waitForVisibilityElement(name);//My own visibility function
        findElement(By.name("customerName")).sendKeys(name);
    }
    catch (StaleElementReferenceException e)
    {
        e.getMessage();
    }
}

我尝试过使用 但过时异常仍然间歇性地抛出。ExpectedConditions.presenceOfElementLocated(By)

希望这个解决方案有所帮助。

0赞 Ashok M A 7/5/2016 #14

这个解决方案对我来说效果很好:

添加错误处理功能,然后重试

var pollLoop = function () {
      element(by.id('spinnerElem')).getAttribute('class').then(function (cls) {
                if (cls.indexOf('spinner-active') > -1) {
                    // wait for the spinner
                } else {
                    //do your logic
                    promise.defer().fulfill();
                }
            }, function () {
                // This err handling function is to handle the {StaleElementReferenceError} and makes sure we find the element always.
                pollLoop();
            });
        };
15赞 Narendra Chandratre 7/13/2016 #15

陈旧元素的两个原因

  1. 在网页上找到的元素,在 WebDriver 中引用为 WebElement,然后 DOM 更改(可能是由于 JavaScript 函数),WebElement 会过时。

  2. 该元素已被完全删除。

当您尝试与过时的 WebElement[上述任何情况] 交互时,将引发 StaleElementException。

如何避免/解决过时的异常?

  1. 将定位器存储到元素而不是参考
driver = webdriver.Firefox();
driver.get("http://www.github.com");
search_input = lambda: driver.find_element_by_name('q');
search_input().send_keys('hello world\n'); 
time.sleep(5);


search_input().send_keys('hello frank\n') // no stale element exception
  1. 利用所用 JS 库中的钩子
   # Using Jquery queue to get animation queue length.
    animationQueueIs = """
    return $.queue( $("#%s")[0], "fx").length;
    """ % element_id
    wait_until(lambda: self.driver.execute_script(animationQueueIs)==0)
  1. 将您的操作移动到 JavaScript 注入中
 self.driver.execute_script("$(\"li:contains('Narendra')\").click()");
  1. 主动等待元素过时
  # Wait till the element goes stale, this means the list has updated
  wait_until(lambda: is_element_stale(old_link_reference))

这个解决方案对我有用,如果您有任何其他适合您的情况,我在这里提到过,请在下面发表评论

评论

3赞 Chad Lehman 4/29/2020
这是最完整、最不骇人听闻的答案。投赞成票。
0赞 user1920925 10/3/2016 #16

在对问题进行深入调查后,我发现选择仅为 Bootstrap 添加的 DIV 元素时会出现错误。Chrome 浏览器删除了此类 DIV,并发生错误。下台并选择实际元素来修复错误就足够了。例如,我的模式对话框具有结构:

<div class="modal-content" uib-modal-transclude="">
    <div class="modal-header">
        ...
    </div>
    <div class="modal-body">
        <form class="form-horizontal ...">
            ...
        </form>
    <div>
<div>

选择 div class=“modal-body” 会生成错误,选择 form ... 会正常工作。

0赞 Ben Wilson 11/5/2016 #17

就我而言,此错误是由于我在

def parse(self, response):

当使用Selenium和Scrapy的组合时的方法,例如:

不起作用:

class MySpider(scrapy.Spider):
     action_chains = ActionChains(self.driver)

向内移动解决了问题,例如:action_chains = ActionChains(self.driver)def parse(self, response):

工程:

def parse(self, response):
     self.driver.get(response.url)
     action_chains = ActionChains(self.driver)
-2赞 virender rana 6/30/2017 #18

只需下载新的 chrome 扩展程序并使用 selenium server 3 即可正常工作。

0赞 James Affleck 9/16/2017 #19

我发现避免过时元素引用的最好方法是不使用 PageFactory,而是存储定位器(即按元素)。

public class WebDriverFactory {

    // if you want to multithread tests, use a ThreadLocal<WebDriver> 
    // instead.
    // This also makes it so you don't have to pass around WebDriver objects
    // when instantiating new Page classes
    private static WebDriver driver = null;

    public static WebDriver getDriver() {
       return driver;
    }
    public static void setDriver(WebDriver browser)  {
       driver = browser;
    }       
}

// class to let me avoid typing out the lengthy driver.findElement(s) so 
// much
public Abstract class PageBase {
    private WebDriver driver = WebDriverFactory.getDriver();

    // using var args to let you easily chain locators
    protected By getBy(By... locator) {
      return new ByChained(locator);
    }

    protected WebElement find(By... locators) {
      return driver.findElement(getBy(locators));
    }

    protected List<WebElement> findEm(By... locators) {
      return driver.findElements(getBy(locators));
    }

    protected Select select(By... locators) {
      return new Select(getBy(locators));
    }
}

public class somePage extends PageBase {
  private static WebDriver driver = WebDriverFactory.getDriver();
  private static final By buttonBy = By.cssSelector(".btn-primary");

  public void clickButton() {
     WebDriverWait wait = new WebDriverWait(driver, 10);
     wait.until(ExpectedConditions.elementToBeClickable(buttonBy));
     find(buttonBy).click();
  }

}

我有一个充满静态 WebDriverWait 方法的类。而且我不记得上面使用的 WebDriver wait 是否会处理 StaleElement 异常。如果没有,你可以像 DjangoFan 的回答一样使用流畅的等待。但是我展示的原理会起作用(即使带有 WebDriverWait 的特定行爆炸了。

所以 tldr;

  1. 使用定位符,以及 WebDriverWait/Fluent wait/ 的组合,自己重新定位元素,所以如果你的元素过时了,你可以重新定位它,而不必在(对于 pagefactory 初始化的元素)中复制定位符,因为没有 WebElement.relocate() 方法。@FindBy
  2. 为了简化生活,有一个 Abstract BasePage 类,其中包含用于查找元素/元素列表的便捷方法。

评论

0赞 James Affleck 11/1/2019
过了一会儿,我发现这种方法不太理想。相反,我会捕获有问题的块,使用显式等待条件,然后再次重新初始化正在运行的页面(initElements)。
0赞 Silverbullet 10/25/2017 #20

我尝试了上述许多建议,但最简单的建议奏效了。就我而言,对 Web 元素使用 @CachelookUp 导致了过时的元素异常。我猜刷新页面后,元素引用没有重新加载,找不到元素。禁用元素的@CachelookUp行有效。

    //Search button
    @FindBy(how=How.XPATH, using =".//input[@value='Search']")  
    //@CachelookUp
    WebElement BtnSearch;
1赞 Nag Raj 6/25/2018 #21

当发生过时元素异常时!!

当支持这些文本框/按钮/链接的库发生更改时,可能会发生过时元素异常,这意味着元素相同,但引用现在在网站中已更改,而不会影响定位器。因此,我们存储在缓存中的引用(包括库引用)现在已经过时或过时了,因为页面已使用更新的库刷新。

for(int j=0; j<5;j++)
try {
    WebElement elementName=driver.findElement(By.name(“createForm:dateInput_input”));
    break;
} catch(StaleElementReferenceException e){
e.toString();
System.out.println(“Stale element error, trying ::  ” + e.getMessage());
}
elementName.sendKeys(“20/06/2018”);
0赞 Marek Andreansky 1/13/2021 #22

在 Selenium 3 中,您可以使用 ExpectedConditions.refreshed(your condition)。

它将处理 StaleElementReferenceException 并重试该条件。