【问题标题】:Selenium Webdriver with Java: Element not found in the cache - perhaps the page has changed since it was looked up带有 Java 的 Selenium Webdriver:在缓存中找不到元素 - 页面可能在查找后已更改
【发布时间】:2013-08-01 02:17:19
【问题描述】:

我在课堂开始时初始化一个变量:

public WebElement logout;

稍后在代码中,在某些方法中,当我第一次遇到注销按钮时,我为该变量赋值(在 if/else 语句的括号中):

logout = driver.findElement(By.linkText("Logout"));
logout.click();

然后我在测试的另一个阶段再次成功地使用“注销”:

logout.click();

并且在测试结束时,在元素相同的地方(By.linkText("Logout")),我得到了这个错误:

Element not found in the cache - perhaps the page has changed since it was looked up

为什么?

编辑:实际上,我没有成功使用 logout.click();在我测试的另一个阶段发出命令。看来我不能再用了。我必须创建一个 logout1 webelement 并使用它...

【问题讨论】:

  • 在您的参考有效和不再有效之间的任何时候页面是否发生了变化?
  • 不,据我所知没有任何变化。没有人部署任何东西,我使用了一些 ajax 的东西,但链接文本保持不变,并且链接仍在页脚中
  • 如果已执行 AJAX,则页面可能已更改 - 因此,由于 DOM 已更改,对您元素的 WebDriver 引用现在将“陈旧”。如果您在尝试在通常会中断的阶段单击它之前再次尝试 find 元素会发生什么?一个想法,为什么不创建一个logout 方法,在每次需要时查找并单击该元素?
  • 哦,我明白了 - 它第一次查找链接文本并以其他方式记录结果,与 DOM 相关,因此第二次调用变量不会查找链接文本,但对于 DOM 参考?尝试了你的方法,它奏效了!如果你用那个帖子回答我的问题,我会接受。

标签: java selenium webdriver


【解决方案1】:

如果在您最初找到element 后页面有任何更改,webdriver 引用现在将包含stale 引用。随着页面的变化,element 将不再是 webdriver 期望的位置。

要解决您的问题,请在每次需要使用该元素时尝试 finding 该元素 - 编写一个您可以随时调用的小方法是个好主意。

import org.openqa.selenium.support.ui.WebDriverWait

public void clickAnElementByLinkText(String linkText) {
    wait.until(ExpectedConditions.presenceOfElementLocated(By.linkText(linkText)));
    driver.findElement(By.linkText(linkText)).click();
}

然后在您的代码中,您只需要:

clickAnElementByLinkText("Logout");

因此,每次它都会找到该元素并单击它,因此即使页面发生更改,因为它正在“刷新”对该元素的引用,它都会成功单击它。

【讨论】:

  • 确实很有帮助!
  • 欢迎,希望对您有所帮助。 :)
  • 如果页面上运行了 javascript 来操作 DOM(例如,动态弹出窗口),由于竞争条件仍然可能引发此异常。
  • 我尝试了这段代码,但我收到一条错误消息“无法解析符号'等待'”我应该导入什么?
  • 你可以试试这个:WebDriverWait wait = new WebDriverWait(driver, 10);http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp
【解决方案2】:

浏览器重建了动态页面的DOM结构,元素不需要保留,使用前必须找到。

例如使用 XPath。这种做法是不正确的(将来可能会导致异常org.openqa.selenium.StaleElementReferenceException):

WebElement element = driver.findElement(By.xpath("//ul[@class=\"pagination\"]/li[3]/a"));
...// Some Ajax interaction here
element.click(); //<-- Element might not be exists

这种做法是正确的:

driver.findElement(By.xpath("//ul[@class=\"pagination\"]/li[3]/a")).click();

【讨论】:

    【解决方案3】:

    这是因为您没有给适当的时间来加载页面。所以您必须为给定页面提供Thread.sleep(); 代码。
    我的项目也遇到了同样的问题,但在使用 Thread.sleep(); 后,它对我来说工作正常,尽可能多地为网页提供 30 到 50 秒。

    【讨论】:

    • 问题实际上是在将元素分配给变量后页面发生了变化。因此,陈旧的参考。
    • 为@nabsATX +1。更具体地说,在集成测试或验收测试中,当我看到 sleep() (无论是什么语言)时总是有异味:它会减慢测试速度,除了在实时系统中,它从不保证线程/进程您正在等待的将被优先考虑。相反,询问您在等待什么事件。 Cf 以测试为指导的成长型面向对象软件第 27 章:测试异步代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多