选择 HTML 表格行时“元素不再附加到 DOM”StaleElementReferenceException

软件测试 网络驱动程序 硒2 爪哇 路径
2022-01-19 17:38:21

我正在使用 Selenium 2/WebDriver 进行自动化。我有一张桌子,正在尝试在其中选择一行。当测试运行时,我可以看到该行变得突出显示,就像它被单击一样,但随后我立即收到"org.openqa.selenium.StaleElementReferenceException: Element is no longer attached to the DOM"错误并且测试失败。

代码如下:

@Test
public void rowSelection() throws Exception
{
    SeleniumHelper helper = new SeleniumHelper();
    action = new SeleniumActionHelper(driver);

    helper.login();

    String testUrl = navigateToUrl("option/listOptions.xhtml");
    driver.get(testUrl);

    WebElement table = findElementById("tableSection:dataTableWrapped_data");
    List<WebElement> allRows = table.findElements(By.tagName("tr"));
    for (WebElement row : allRows)
        {
            List<WebElement> cells = row.findElements(By.tagName("td"));
            for (WebElement cell : cells)
            {
                WebElement listName = cell.findElement(By.xpath("./* [text()='body_build']"));
                listName.click();
            }
        }
}

Thread.sleep(2000)在动作前后都放了一个listName.click(),但都没有帮助。任何帮助将不胜感激。

3个回答

我认为您的页面(或其中的一部分)在执行后重新加载listName.click()

重新加载后还有一个表,它似乎与重新加载前的表相同,但不是同一个。您可以计算表中的行/列并在循环中使用迭代器。您将需要重复

WebElement table = findElementById("tableSection:dataTableWrapped_data");
List<WebElement> allRows = table.findElements(By.tagName("tr"));

listName.click();

Stale element出现的两个原因

  1. 在 WebDriver 中作为 WebElement 引用的网页上找到的元素,然后 DOM 发生变化(可能是由于 JavaScript 函数),WebElement 变得陈旧。

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

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

解决方案:

  1. 将定位器存储到元素而不是引用

driver = webdriver.Firefox();
driver.get("http://www.github.com");
search_input = driver.find_element_by_name('q');

search_input.send_keys('hello world\n'); // Page contents refresh after typing in search results.
time.sleep(5);

search_input.send_keys('hello frank\n'); // StaleElementReferenceException

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)
    
  2. 将您的操作转移到 JavaScript 注入中

    self.driver.execute_script("$(\"li:contains('Narendra')\").click()");
    
  3. 主动等待元素过时

    # Wait till the element goes stale, this means the list has updated
    wait_until(lambda: is_element_stale(old_link_reference))
    

该解决方案对我有用,如果您有任何其他适用于您的方案,我在这里提到过,然后在下面评论或联系我,以便我们可以添加到解决方案列表中

我们有机会看到您尝试自动化的页面吗?我能想到一个原因,即表格的开发方式是有 javascript,当与元素交互而不是修改元素时,它会用新元素替换它,在这种情况下,该元素将不再存在...

如果你在 Firefox 或 IE 开发者工具中使用 firebug 之类的东西来查看 dom,当鼠标悬停在它上面时,有问题的元素会改变吗?如果开发人员实际上是在替换元素而不是修改它的类,那将是一个非常奇怪的实现,我认为你应该提交一个错误并让他们改变它的实现方式。