Django:Selenium-浏览器上的陈旧元素参考
Django: Selenium- stale element reference on browse
我正在使用 Chrome webdriver,因为 Firefox webdriver 在我的 Windows PC 上似乎有问题。
我的 Django 功能测试在我去度假之前工作得很好,但现在它们会抛出各种错误。
有时,当我尝试在页面上查找元素时,我得到:
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
其他时候,尝试验证 url 失败,因为 Selenium 似乎正在读取上一页的 URL。失败点似乎从运行变成了运行,换句话说,测试的某些部分在执行之间可以在成功和不成功之间交替。但是,问题似乎总是在使用 .click()
.
后出现
在查看浏览器时,Selenium 似乎已成功导航到该页面,所以我想它只是太快地寻找项目——在它们存在于浏览器之前。
将 implicitly.wait()
添加到我的 setUpClass 似乎没有帮助,但我可能用错了。
我尝试了 Harry Percival's site 中的有前途的想法(如下),但 Selenium 只是在等待页面时超时。
from contextlib import contextmanager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import \
staleness_of
class MySeleniumTest(SomeFunctionalTestClass):
# assumes self.browser is a selenium webdriver
@contextmanager
def wait_for_page_load(self, timeout=30):
old_page = self.browser.find_element_by_tag_name('html')
yield
WebDriverWait(self.browser, timeout).until(
staleness_of(old_page)
)
def test_stuff(self):
# example use
with self.wait_for_page_load(timeout=10):
self.browser.find_element_by_link_text('a link')
# nice!
有没有其他人处理过这个问题?我应该遵循什么正确的方法来解决这个问题?
编辑:
发布的解决方案非常有效并且真正清理了我的代码,因为我可以简单地将 .click() 添加到被调用函数,就像描述的那样。
以下是帮助我进行自定义的文档:
Documentation for the syntax for By for modification purposes.
Documentation for Selenium's Expected Conditions
注意:我使用术语 "browser" 代替驱动程序,我认为这是最初让我失望的原因。
wait_for_page_load一定要是发电机吗?我认为它会 return 无需等待!这就是为什么你的测试不稳定。有时元素会在您调用时加载 find_element_by_link_text 有时不会。
我已经成功地使用了这种方法:
from selenium.webdriver.support import expected_conditions as EC
def wait_for_element(self, elm, by = 'id', timeout=10) :
wait = WebDriverWait(self.driver, timeout)
if by == 'id' :
element = wait.until(EC.element_to_be_clickable((By.ID,elm)))
return self.driver.find_element_by_id(elm)
elif by == 'link':
wait.until(EC.element_to_be_clickable( (By.LINK_TEXT,elm)))
return self.driver.find_element_by_link_text(elm)
# by tag, by css etc etc goes here.
我使用 dom 元素的显着 ID 调用此方法,该元素应在与页面交互之前显示。 returned 元素可以直接交互。
我正在使用 Chrome webdriver,因为 Firefox webdriver 在我的 Windows PC 上似乎有问题。
我的 Django 功能测试在我去度假之前工作得很好,但现在它们会抛出各种错误。
有时,当我尝试在页面上查找元素时,我得到:
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
其他时候,尝试验证 url 失败,因为 Selenium 似乎正在读取上一页的 URL。失败点似乎从运行变成了运行,换句话说,测试的某些部分在执行之间可以在成功和不成功之间交替。但是,问题似乎总是在使用 .click()
.
在查看浏览器时,Selenium 似乎已成功导航到该页面,所以我想它只是太快地寻找项目——在它们存在于浏览器之前。
将 implicitly.wait()
添加到我的 setUpClass 似乎没有帮助,但我可能用错了。
我尝试了 Harry Percival's site 中的有前途的想法(如下),但 Selenium 只是在等待页面时超时。
from contextlib import contextmanager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import \
staleness_of
class MySeleniumTest(SomeFunctionalTestClass):
# assumes self.browser is a selenium webdriver
@contextmanager
def wait_for_page_load(self, timeout=30):
old_page = self.browser.find_element_by_tag_name('html')
yield
WebDriverWait(self.browser, timeout).until(
staleness_of(old_page)
)
def test_stuff(self):
# example use
with self.wait_for_page_load(timeout=10):
self.browser.find_element_by_link_text('a link')
# nice!
有没有其他人处理过这个问题?我应该遵循什么正确的方法来解决这个问题?
编辑: 发布的解决方案非常有效并且真正清理了我的代码,因为我可以简单地将 .click() 添加到被调用函数,就像描述的那样。
以下是帮助我进行自定义的文档:
Documentation for the syntax for By for modification purposes.
Documentation for Selenium's Expected Conditions
注意:我使用术语 "browser" 代替驱动程序,我认为这是最初让我失望的原因。
wait_for_page_load一定要是发电机吗?我认为它会 return 无需等待!这就是为什么你的测试不稳定。有时元素会在您调用时加载 find_element_by_link_text 有时不会。
我已经成功地使用了这种方法:
from selenium.webdriver.support import expected_conditions as EC
def wait_for_element(self, elm, by = 'id', timeout=10) :
wait = WebDriverWait(self.driver, timeout)
if by == 'id' :
element = wait.until(EC.element_to_be_clickable((By.ID,elm)))
return self.driver.find_element_by_id(elm)
elif by == 'link':
wait.until(EC.element_to_be_clickable( (By.LINK_TEXT,elm)))
return self.driver.find_element_by_link_text(elm)
# by tag, by css etc etc goes here.
我使用 dom 元素的显着 ID 调用此方法,该元素应在与页面交互之前显示。 returned 元素可以直接交互。