python - Django:Selenium-浏览器上的陈旧元素引用

标签 python django selenium django-testing

我正在使用 Chrome webdriver,因为 Firefox webdriver 在我的 Windows PC 上似乎有问题。

我的 Django 功能测试在我去度假之前工作得很好,但现在它们会抛出各种错误。

有时,当我尝试在页面上查找元素时,我得到:

selenium.common.exceptions.StaleElementReferenceException:消息:过时的元素引用:元素未附加到页面文档

其他时候,验证 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

注意:我使用术语“浏览器”代替驱动程序,我认为这是最初让我失望的原因。

最佳答案

wait_for_page_load 必须是生成器吗?我想它会不等而归!这就是为什么你的测试不稳定。有时元素会在您调用 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 调用这个方法,它应该在页面可以交互之前显示。返回的元素可以直接交互。

关于python - Django:Selenium-浏览器上的陈旧元素引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32030816/

相关文章:

python写入不同的文件

python - StringIO 导入 ee 时出现问题,尽管可以单独导入

python - 如何为 Jupyter Notebook 安装 selenium?

java - 查找定位器 Selenium Webdriver - IE8 时遇到问题。无法浏览菜单

python - 我如何从 python unittest 发出测试错误(不是失败)的信号

python - 如何为python3安装flask-mysql?

python - 条件列显示,django-tables2

python - 如何将 django 项目(以及依赖的 Python 模块)压缩到一个可以在服务器上运行的文件中

django - 使用模型 ID 列表调用 django rest API

java - 程序化浏览性能问题