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

2k views Asked by At

I am following guide to learn TDD with python. At some point, after doing migrations, the output of command python3 functional_tests.py should be (according to book):

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

But I am getting error:

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

And after trying second (and more) time:

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.

I've been googling and searching SO for similar problems, but didn't find one that could help me solve the issue.
I am using geckodriver, and adding it's path to PATH.

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

Should I switch to Chrome? It's not trivial, it would require some time from me, but can it work? Is more like Firefox or Selenium? I don't think it's code related - I cloned repo for chapter 5 and same crash is happening.

2

There are 2 answers

0
hwjp On BEST ANSWER

It's because the book is expecting you to use Selenium 2, not Selenium 3. v3 has quite different behaviour with regards to implicit waits (and quite a few bugs last time I checked) so it's simplest to stick with Selenium 2 for now.

Have another look at the installation instructions: http://www.obeythetestinggoat.com/book/pre-requisite-installations.html

0
mgbennet On

The error arises because earlier in the chapter we add a redirect after a POST request. The page briefly refreshes, and that can screw up Selenium. If you want to stick with Selenium 3, I found a fix for this on the blog for the book: http://www.obeythetestinggoat.com/how-to-get-selenium-to-wait-for-page-load-after-a-click.html.

Basically, you add a method to the NewVisitorTest class that lets you to wait for the page to reload, and then continues with the assert tests.

...
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")