使用Protractor访问上一页元素的正确方法是什么?

时间:2017-08-19 16:34:21

标签: selenium protractor

我有一个测试,点击页面上的链接列表。如果我在新页面中打开链接,我可以使用browser.switchTo()。窗口和原始窗口的句柄遍历列表,点击每个链接。

但是,如果我在同一页面(_self)中打开一个链接,并使用browser.navigate()。back()导航回原始链接列表,迭代时单击下一个链接会出现以下错误:

StaleElementReferenceError: stale element reference: element is not attached to the page document

在您离开后,访问先前页面上元素的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

当您从Selenium请求对象时,使用内部唯一ID对象的Selenium ID。请参阅以下命令

>>> driver.find_element_by_tag_name("a")
<selenium.webdriver.firefox.webelement.FirefoxWebElement 
(session="93fc2bec-c9f8-0c46-aec3-1939af00c917", 
element="5173f7fb-63ca-e447-b176-4a226d956834")>

正如您所见,该元素具有唯一的uuid。 Selenium在内部维护这些列表,因此当您执行click操作时,它会从缓存中获取元素并对其执行操作。

刷新页面或加载新页面后,此缓存不再有效。但是您在语言绑定中创建的对象仍然是。如果我尝试在其

上执行某些操作
>>> elem.is_displayed()
selenium.common.exceptions.StaleElementReferenceException: 
Message: The element reference of [object Null] null 
stale: either the element is no longer attached to the DOM or the page has been refreshed

所以简而言之,没有办法使用同一个对象。这意味着你需要改变你的方法。请考虑以下代码

for elem in driver.find_elements_by_tag_name("a"):
    elem.click()
    driver.back()

上述代码将在elem.click()的第二次尝试时失败。所以修复是确保不重用集合对象。而是使用基于数字的循环。我可以用许多不同的方式编写上面的代码。考虑以下几种方法

方法1

elems = driver.find_elements_by_tag_name("a")
count = len(elems)
for i in range(0, count):
    elems[i].click()
    driver.back()
    elems = driver.find_elements_by_tag_name("a")

这不是一个非常好的方法,因为我得到一个对象集合,只使用其中一个。一个有500多个奇数链接的页面将使这段代码变得非常慢

方法2

elems = driver.find_elements_by_tag_name("a")
count = len(elems)
for i in range(1, count + 1):
    elem = driver.find_element_by_xpath("(//a)[{}]".format(i))
    driver.back()

这比方法1更好,因为我只获得一个对象。后来我得到一个并使用一个

方法3

elems = driver.find_elements_by_tag_name("a")
links = []

for elem in elems:
    links.append(elem.get_attribute("href"))

for link in links:
    driver.get(link)
    # do some action

此方法仅在链接基于href时有效。所以根据情况,我会选择或改变我的方法