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:
parent
964342fa38
commit
636376468d
@ -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),
|
||||||
|
@ -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)
|
||||||
|
@ -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))
|
||||||
|
Loading…
Reference in New Issue
Block a user