Selenium 无法访问死的 object/The 元素引用已过时

Selenium can't access dead object/The element reference is stale

我正在关注 guide to learn TDD with python. At some point,在进行迁移之后,命令 python3 functional_tests.py 的输出应该是(根据书本):

self.fail('Finish the test!')
AssertionError: Finish the test!

但我收到错误消息:

selenium.common.exceptions.InvalidSelectorException: Message: Given css selector expression "tr" is invalid: TypeError: can't access dead object

在尝试第二次(或更多次)之后:

selenium.common.exceptions.StaleElementReferenceException: Message: The element reference is stale. Either the element is no longer attached to the DOM or the page has been refreshed.

我一直在谷歌搜索和搜索类似问题,但没有找到可以帮助我解决问题的问题。
我正在使用 geckodriver,并将它的路径添加到 PATH

Django==1.8.7
selenium==3.0.2
Mozilla Firefox 50.0.2
(X)Ubuntu 16.04

我应该切换到 Chrome 吗?这不是微不足道的,它需要我一些时间,但它可以工作吗?更像 Firefox 还是 Selenium?我认为这与代码无关 - 我克隆了 repo for chapter 5 并且发生了同样的崩溃。

这是因为这本书希望您使用 Selenium 2,而不是 Selenium 3。v3 在隐式等待方面有完全不同的行为(我上次检查时有很多错误)所以坚持使用 Selenium 2 是最简单的现在。

再看一下安装说明:http://www.obeythetestinggoat.com/book/pre-requisite-installations.html

错误的出现是因为在本章的前面我们在 POST 请求之后添加了重定向。页面会短暂刷新,这可能会搞砸 Selenium。如果您想坚持使用 Selenium 3,我在本书的博客上找到了解决此问题的方法:http://www.obeythetestinggoat.com/how-to-get-selenium-to-wait-for-page-load-after-a-click.html.

基本上,您向 NewVisitorTest class 添加一个方法,让您等待页面重新加载,然后继续断言测试。

...
from contextlib import contextmanager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import staleness_of

class NewVisitorTest(unittest.TestCase):
    ...
    @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_can_start_list_and_retrieve_it_later(self):
        ...
        inputbox.send_keys("Buy peacock feathers")
        inputbox.send_keys(Keys.ENTER)

        with self.wait_for_page_load(timeout=10):
            self.check_for_row_in_list_table("1: Buy peacock feathers")

        inputbox = self.browser.find_element_by_id("id_new_item")
        inputbox.send_keys("Use peacock feathers to make a fly")
        inputbox.send_keys(Keys.ENTER)

        with self.wait_for_page_load(timeout=10):
            self.check_for_row_in_list_table("1: Buy peacock feathers")
            self.check_for_row_in_list_table("2: Use peacock feathers to make a fly")