Reduce the chance of Selenium timeouts in integration tests

Avoid situations when we trying to take something out of a destroyed
box (contents of an element that is no longer there). Plus other
improvements to a couple of element getter functions/predicates that
might had been causing timeouts.

Related-Bug: #1467950
Implements blueprint: integration-tests-hardening

Change-Id: Ia17cb2134eaa5dd14a04384d1b703a8a648f952d
This commit is contained in:
Timur Sufiev 2015-08-20 14:41:49 +03:00
parent 964342fa38
commit 636376468d
3 changed files with 28 additions and 4 deletions

View File

@ -24,10 +24,13 @@ class BaseWebObject(unittest.TestCase):
def _is_element_present(self, *locator): def _is_element_present(self, *locator):
try: try:
self._turn_off_implicit_wait()
self._get_element(*locator) self._get_element(*locator)
return True return True
except Exceptions.NoSuchElementException: except Exceptions.NoSuchElementException:
return False return False
finally:
self._turn_on_implicit_wait()
def _is_element_visible(self, *locator): def _is_element_visible(self, *locator):
try: try:
@ -84,8 +87,16 @@ class BaseWebObject(unittest.TestCase):
predicate) predicate)
def _wait_till_text_present_in_element(self, element, text, timeout=None): def _wait_till_text_present_in_element(self, element, text, timeout=None):
self._wait_until(lambda x: self._is_text_visible(element, text), """Waiting for a text to appear in a certain element very often is
timeout) actually waiting for a _different_ element with a different text to
appear in place of an old element. So a way to avoid capturing stale
element reference should be provided for this use case.
"""
def predicate(_):
elt = element() if hasattr(element, '__call__') else element
return self._is_text_visible(elt, text)
self._wait_until(predicate, timeout)
def _wait_till_element_visible(self, element, timeout=None): def _wait_till_element_visible(self, element, timeout=None):
self._wait_until(lambda x: self._is_element_displayed(element), self._wait_until(lambda x: self._is_element_displayed(element),

View File

@ -66,6 +66,7 @@ class BasePage(pageobject.PageObject):
def _wait_till_spinner_disappears(self): def _wait_till_spinner_disappears(self):
try: try:
self._turn_off_implicit_wait()
spinner = self._get_element(*self._spinner_locator) spinner = self._get_element(*self._spinner_locator)
self._wait_till_element_disappears(spinner) self._wait_till_element_disappears(spinner)
except NoSuchElementException: except NoSuchElementException:
@ -73,6 +74,8 @@ class BasePage(pageobject.PageObject):
# even before Selenium get a chance to get the spinner element, # even before Selenium get a chance to get the spinner element,
# it will raise the NoSuchElementException exception. # it will raise the NoSuchElementException exception.
pass pass
finally:
self._turn_on_implicit_wait()
def change_project(self, name): def change_project(self, name):
self.topbar.user_dropdown_project.click_on_project(name) self.topbar.user_dropdown_project.click_on_project(name)

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from selenium.common import exceptions
from selenium.webdriver.common import by from selenium.webdriver.common import by
from openstack_dashboard.test.integration_tests.pages import basepage from openstack_dashboard.test.integration_tests.pages import basepage
@ -106,8 +107,17 @@ class ImagesPage(basepage.BaseNavigationPage):
def is_image_active(self, name): def is_image_active(self, name):
row = self._get_row_with_image_name(name) row = self._get_row_with_image_name(name)
return row.cells[self.IMAGES_TABLE_STATUS_COLUMN_INDEX].text == \
'Active' # NOTE(tsufiev): better to wrap getting image status cell in a lambda
# to avoid problems with cell being replaced with totally different
# element by Javascript
def cell_getter():
return row.cells[self.IMAGES_TABLE_STATUS_COLUMN_INDEX]
try:
self._wait_till_text_present_in_element(cell_getter, 'Active')
except exceptions.TimeoutException:
return False
return True
def wait_until_image_active(self, name): def wait_until_image_active(self, name):
self._wait_until(lambda x: self.is_image_active(name)) self._wait_until(lambda x: self.is_image_active(name))