【问题标题】:Django: Selenium- stale element reference on browseDjango:Selenium-浏览时的陈旧元素参考
【发布时间】:2015-11-08 22:26:09
【问题描述】:

我正在使用 Chrome 网络驱动程序,因为 Firefox 网络驱动程序在我的 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

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

【问题讨论】:

    标签: python django selenium django-testing


    【解决方案1】:

    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 调用这个方法,该 dom 元素应该在页面交互之前显示出来。返回的元素可以直接交互。

    【讨论】:

    • 嗯,看来我需要熟悉预期条件语法才能使其适用于我的情况。不知何故,Selenium 在点击后但在加载下一个 URL 之前比较 URL。我试着弄乱这个,但它仍然超时,所以我认为我的构造不正确。
    • 如果你用 wait_for_element 替换你对 wait_for_page_load 的调用,我已经发布了它可以工作。例如 wait_for_element('a link','link',30) 应该这样做。但是 30 秒有点太长了
    • 抱歉,我不得不离开这一段时间。我已经坐下来让它工作了,我很高兴我做到了!非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 2019-08-10
    • 1970-01-01
    • 2018-01-04
    • 2018-08-21
    相关资源
    最近更新 更多