Opened 5 years ago

Closed 5 years ago

#30973 closed Bug (fixed)

Selenium wait_page_loaded waits for wrong page (race condition)

Reported by: Johannes Maron Owned by: Johannes Maron
Component: Testing framework Version: dev
Severity: Normal Keywords: selenium
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Right now django.contrib.admin.tests.AdminSeleniumTestCase.wait_page_loaded waits for the body HTML-tag to be present. It is meant to be executed after a page reload is triggered, like a form submit.

However, if the test suite is a little faster than our browser (race condition), we are looking get confirmation for the body tag of the old page, not the new one.

The safe (and correct) way to wait in selenium for a page to re reloaded is to wait until the old one is gone and the new one is ready. Preferably with a context manager like so:

@contextmanager
def wait_page_loaded(self, timeout=10):
    """
    Block until page has started to load.
    """
    from selenium.common.exceptions import TimeoutException
    from selenium.webdriver.support import expected_conditions as ec

    try:
        old_page = self.selenium.find_element_by_tag_name('html')
        yield
        # Wait for the next page to be loaded
        self.wait_until(ec.staleness_of(old_page), timeout=timeout)
        self.wait_until(
            lambda driver:
                driver.execute_script('return document.readyState;') == 'complete',
            timeout=timeout

        )
    except TimeoutException:
        # IE7 occasionally returns an error "Internet Explorer cannot
        # display the webpage" and doesn't load the next page. We just
        # ignore it.
        pass

In some cases we might also want to wait for a site to be ready after a regular selenium.get.
In that case with should have a separate method, like so:

    def wait_page_ready(self, timeout=10):
        """
        Block until page has started to load.
        """
        self.wait_until(
            lambda driver: driver.execute_script('return document.readyState;') == 'complete',
            timeout
        )

This bug currently affects a lot of tests and fails preferably when you run FireFox but I've seen it on Chrome too.

Change History (4)

comment:1 by Johannes Maron, 5 years ago

Has patch: set
Owner: changed from nobody to Johannes Maron
Status: newassigned

comment:2 by Carlton Gibson, 5 years ago

Triage Stage: UnreviewedAccepted

Hey Joe. Yes, super. I am very happy to review PRs making the Selenium tests more stable :)

comment:3 by Carlton Gibson, 5 years ago

Triage Stage: AcceptedReady for checkin

comment:4 by Carlton Gibson <carlton.gibson@…>, 5 years ago

Resolution: fixed
Status: assignedclosed

In 69dbb6b7:

Fixed #30973 -- Converted selenium tests wait_page_loaded to context manager.

Note: See TracTickets for help on using tickets.
Back to Top