From 636376468d06bdd9cb3dbdd133b375c3c1eaadc1 Mon Sep 17 00:00:00 2001 From: Timur Sufiev Date: Thu, 20 Aug 2015 14:41:49 +0300 Subject: [PATCH] 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 --- .../test/integration_tests/basewebobject.py | 15 +++++++++++++-- .../test/integration_tests/pages/basepage.py | 3 +++ .../pages/project/compute/imagespage.py | 14 ++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/openstack_dashboard/test/integration_tests/basewebobject.py b/openstack_dashboard/test/integration_tests/basewebobject.py index ec21bf1fc0..be1ac47f53 100644 --- a/openstack_dashboard/test/integration_tests/basewebobject.py +++ b/openstack_dashboard/test/integration_tests/basewebobject.py @@ -24,10 +24,13 @@ class BaseWebObject(unittest.TestCase): def _is_element_present(self, *locator): try: + self._turn_off_implicit_wait() self._get_element(*locator) return True except Exceptions.NoSuchElementException: return False + finally: + self._turn_on_implicit_wait() def _is_element_visible(self, *locator): try: @@ -84,8 +87,16 @@ class BaseWebObject(unittest.TestCase): predicate) def _wait_till_text_present_in_element(self, element, text, timeout=None): - self._wait_until(lambda x: self._is_text_visible(element, text), - timeout) + """Waiting for a text to appear in a certain element very often is + 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): self._wait_until(lambda x: self._is_element_displayed(element), diff --git a/openstack_dashboard/test/integration_tests/pages/basepage.py b/openstack_dashboard/test/integration_tests/pages/basepage.py index 826ffc08c1..5a1e795739 100644 --- a/openstack_dashboard/test/integration_tests/pages/basepage.py +++ b/openstack_dashboard/test/integration_tests/pages/basepage.py @@ -66,6 +66,7 @@ class BasePage(pageobject.PageObject): def _wait_till_spinner_disappears(self): try: + self._turn_off_implicit_wait() spinner = self._get_element(*self._spinner_locator) self._wait_till_element_disappears(spinner) except NoSuchElementException: @@ -73,6 +74,8 @@ class BasePage(pageobject.PageObject): # even before Selenium get a chance to get the spinner element, # it will raise the NoSuchElementException exception. pass + finally: + self._turn_on_implicit_wait() def change_project(self, name): self.topbar.user_dropdown_project.click_on_project(name) diff --git a/openstack_dashboard/test/integration_tests/pages/project/compute/imagespage.py b/openstack_dashboard/test/integration_tests/pages/project/compute/imagespage.py index 90a1863dfb..790ec7adf4 100644 --- a/openstack_dashboard/test/integration_tests/pages/project/compute/imagespage.py +++ b/openstack_dashboard/test/integration_tests/pages/project/compute/imagespage.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +from selenium.common import exceptions from selenium.webdriver.common import by from openstack_dashboard.test.integration_tests.pages import basepage @@ -106,8 +107,17 @@ class ImagesPage(basepage.BaseNavigationPage): def is_image_active(self, 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): self._wait_until(lambda x: self.is_image_active(name))