我正在使用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(),但都没有帮助。任何帮助将不胜感激。

评论

这可能有助于处理此类元素-stackoverflow.com/questions/4846454/…

#1 楼

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

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

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




listName.click();


评论


显示的最后一个答案是完全正确的。。。

– Bipin Tiwari
2012年12月24日在7:33

#2 楼

发生陈旧元素的两个原因


在WebDriver中被引用为WebElement的网页上找到一个元素,然后DOM更改(可能归因于JavaScript函数),WebElement变得陈旧。
元素已被完全删除。

当您尝试与陈旧的WebElement交互时(以上任何一种情况),都会引发StaleElementException。

要解决的解决方案它们:


将定位符存储到元素中而不是引用中

不要

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




使用的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)



将动作转移到JavaScript注入中

self.driver.execute_script("$(\"li:contains('Narendra')\").click()");



主动等待元素过时

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

/>

此解决方案对我有用,如果您还有其他情况,我在这里已经提到过,对您有用,请在下面评论或与我联系这样我们就可以添加到解决方案列表中

评论


在您的Do代码块中,lambda:关键字是什么?它从何而来 ?这有什么用途 ?

– Stephane
19年8月19日在9:06

永远不要使用固定的等待时间.sleep()使用var el = driver.wait(until.elementLocated()),静态定时总是遵循最坏的情况

– MortenB
19年9月12日在11:39

#3 楼

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

如果您在firefox或IE开发人员工具中使用firebug之类的内容来查看dom,将相关元素悬停在该元素上是否会发生变化?如果开发人员实际上是在替换元素而不是修改元素的类,那将是一个非常奇怪的实现,我认为您应该提交一个错误并让他们更改实现方式。

评论


不幸的是,由于各种原因,我无法显示我们正在处理的页面。该类正在被修改并且没有替换元素...这就是为什么我坐在这里挠头,对我来说这没有意义,因为我可以看到在给出DOM错误之前该行已被选中

–挤压
12年7月13日在21:10

javascript会怎样改变类? Selenium确实会尝试像用户一样操作,并在执行点击之前触发onmouseover之类的事件。如果将鼠标悬停在元素上会使它看起来“已选中”,则可能在触发该事件之后但单击之前发生了陈旧元素异常。

–山姆·伍兹(Sam Woods)
2012年7月13日在21:33