Added the `wait_until()` and `wait_loaded_tag()` methods to `AdminSeleniumWebDriverTestCase` to prevent some concurrency issues with in-memory SQLite database access in the admin Selenium tests. Thanks to Florian Apolloner, Anssi Kääriäinen and Aymeric Augustin for their help debugging this problem.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17283 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
46c12d1293
commit
a343a84ce6
|
@ -29,6 +29,26 @@ class AdminSeleniumWebDriverTestCase(LiveServerTestCase):
|
|||
if hasattr(cls, 'selenium'):
|
||||
cls.selenium.quit()
|
||||
|
||||
def wait_until(self, callback, timeout=10):
|
||||
"""
|
||||
Helper function that blocks the execution of the tests until the
|
||||
specified callback returns a value that is not falsy. This function can
|
||||
be called, for example, after clicking a link or submitting a form.
|
||||
See the other public methods that call this function for more details.
|
||||
"""
|
||||
from selenium.webdriver.support.wait import WebDriverWait
|
||||
WebDriverWait(self.selenium, timeout).until(callback)
|
||||
|
||||
def wait_loaded_tag(self, tag_name, timeout=10):
|
||||
"""
|
||||
Helper function that blocks until the element with the given tag name
|
||||
is found on the page.
|
||||
"""
|
||||
self.wait_until(
|
||||
lambda driver: driver.find_element_by_tag_name(tag_name),
|
||||
timeout
|
||||
)
|
||||
|
||||
def admin_login(self, username, password, login_url='/admin/'):
|
||||
"""
|
||||
Helper function to log into the admin.
|
||||
|
@ -41,6 +61,8 @@ class AdminSeleniumWebDriverTestCase(LiveServerTestCase):
|
|||
login_text = _('Log in')
|
||||
self.selenium.find_element_by_xpath(
|
||||
'//input[@value="%s"]' % login_text).click()
|
||||
# Wait for the next page to be loaded.
|
||||
self.wait_loaded_tag('body')
|
||||
|
||||
def get_css_value(self, selector, attribute):
|
||||
"""
|
||||
|
|
|
@ -1843,6 +1843,41 @@ out the `full reference`_ for more details.
|
|||
</howto/static-files>` so you'll need to have your project configured
|
||||
accordingly (in particular by setting :setting:`STATIC_URL`).
|
||||
|
||||
.. note::
|
||||
|
||||
When using an in-memory SQLite database to run the tests, the same database
|
||||
connection will be shared by two threads in parallel: the thread in which
|
||||
the live server is run, and the thread in which the test case is run. It is
|
||||
important to prevent simultaneous database queries via this shared
|
||||
connection by the two threads as that may sometimes cause the tests to
|
||||
randomly fail. So you need to ensure that the two threads do not access the
|
||||
database at the same time. In particular, this means that in some cases
|
||||
(for example just after clicking a link or submitting a form) you might
|
||||
need to check that a response is received by Selenium and that the next
|
||||
page is loaded before proceeding further with the execution of the tests.
|
||||
This can be achieved, for example, by making Selenium wait until the
|
||||
`<body>` HTML tag is found in the response:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_login(self):
|
||||
from selenium.webdriver.support.wait import WebDriverWait
|
||||
...
|
||||
self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
|
||||
# Wait until the response is received
|
||||
WebDriverWait(self.selenium, timeout).until(
|
||||
lambda driver: driver.find_element_by_tag_name('body'), timeout=10)
|
||||
|
||||
The difficult point is that there really is no such thing as a "page load",
|
||||
especially in modern Web apps that have dynamically-generated page
|
||||
components that do not exist in the HTML initially received from the
|
||||
server. So simply checking for the presence of the `<body>` tag in the
|
||||
response might not necessarily be appropriate for all use cases. Please
|
||||
refer to the `Selenium FAQ`_ and the `Selenium documentation`_ for more
|
||||
information on this topic.
|
||||
|
||||
.. _Selenium FAQ: http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_WebDriver_fails_to_find_elements_/_Does_not_block_on_page_loa
|
||||
.. _Selenium documentation: http://seleniumhq.org/docs/04_webdriver_advanced.html#explicit-waits
|
||||
|
||||
Using different testing frameworks
|
||||
==================================
|
||||
|
|
|
@ -443,6 +443,9 @@ class SeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
|
|||
self.selenium.find_element_by_name('profile_set-2-last_name').send_keys('2 last name 2')
|
||||
self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
|
||||
|
||||
# Wait for the next page to be loaded.
|
||||
self.wait_loaded_tag('body')
|
||||
|
||||
# Check that the objects have been created in the database
|
||||
self.assertEqual(ProfileCollection.objects.all().count(), 1)
|
||||
self.assertEqual(Profile.objects.all().count(), 3)
|
||||
|
|
Loading…
Reference in New Issue