mirror of
https://git.yoctoproject.org/poky
synced 2026-05-30 12:29:55 +00:00
bitbake: toaster-tests: add class SeleniumTestCaseBase for browser tests
In order to reuse the Selenium helper outside a Django environment (for functional testing), add a new module containing the base class SeleniumTestCaseBase, which only inherits unittest.TestCase Add a class SeleniumTestCase with multiple inheritance of StaticLiveServerTestCase and SeleniumTestCaseBase to prevent existing tests from breaking. (Bitbake rev: 1177b3f368d8b7f8557eb649adb2e327b6df801c) Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com> Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
a61eb1f844
commit
1bf1e2c208
@@ -27,186 +27,8 @@
|
|||||||
Helper methods for creating Toaster Selenium tests which run within
|
Helper methods for creating Toaster Selenium tests which run within
|
||||||
the context of Django unit tests.
|
the context of Django unit tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
|
|
||||||
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||||
from selenium import webdriver
|
from tests.browser.selenium_helpers_base import SeleniumTestCaseBase
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
|
||||||
from selenium.common.exceptions import NoSuchElementException, \
|
|
||||||
StaleElementReferenceException, TimeoutException
|
|
||||||
|
|
||||||
def create_selenium_driver(browser='chrome'):
|
class SeleniumTestCase(SeleniumTestCaseBase, StaticLiveServerTestCase):
|
||||||
# set default browser string based on env (if available)
|
pass
|
||||||
env_browser = os.environ.get('TOASTER_TESTS_BROWSER')
|
|
||||||
if env_browser:
|
|
||||||
browser = env_browser
|
|
||||||
|
|
||||||
if browser == 'chrome':
|
|
||||||
return webdriver.Chrome(
|
|
||||||
service_args=["--verbose", "--log-path=selenium.log"]
|
|
||||||
)
|
|
||||||
elif browser == 'firefox':
|
|
||||||
return webdriver.Firefox()
|
|
||||||
elif browser == 'ie':
|
|
||||||
return webdriver.Ie()
|
|
||||||
elif browser == 'phantomjs':
|
|
||||||
return webdriver.PhantomJS()
|
|
||||||
else:
|
|
||||||
msg = 'Selenium driver for browser %s is not available' % browser
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
|
|
||||||
class Wait(WebDriverWait):
|
|
||||||
"""
|
|
||||||
Subclass of WebDriverWait with predetermined timeout and poll
|
|
||||||
frequency. Also deals with a wider variety of exceptions.
|
|
||||||
"""
|
|
||||||
_TIMEOUT = 10
|
|
||||||
_POLL_FREQUENCY = 0.5
|
|
||||||
|
|
||||||
def __init__(self, driver):
|
|
||||||
super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY)
|
|
||||||
|
|
||||||
def until(self, method, message=''):
|
|
||||||
"""
|
|
||||||
Calls the method provided with the driver as an argument until the
|
|
||||||
return value is not False.
|
|
||||||
"""
|
|
||||||
|
|
||||||
end_time = time.time() + self._timeout
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
value = method(self._driver)
|
|
||||||
if value:
|
|
||||||
return value
|
|
||||||
except NoSuchElementException:
|
|
||||||
pass
|
|
||||||
except StaleElementReferenceException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
time.sleep(self._poll)
|
|
||||||
if time.time() > end_time:
|
|
||||||
break
|
|
||||||
|
|
||||||
raise TimeoutException(message)
|
|
||||||
|
|
||||||
def until_not(self, method, message=''):
|
|
||||||
"""
|
|
||||||
Calls the method provided with the driver as an argument until the
|
|
||||||
return value is False.
|
|
||||||
"""
|
|
||||||
|
|
||||||
end_time = time.time() + self._timeout
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
value = method(self._driver)
|
|
||||||
if not value:
|
|
||||||
return value
|
|
||||||
except NoSuchElementException:
|
|
||||||
return True
|
|
||||||
except StaleElementReferenceException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
time.sleep(self._poll)
|
|
||||||
if time.time() > end_time:
|
|
||||||
break
|
|
||||||
|
|
||||||
raise TimeoutException(message)
|
|
||||||
|
|
||||||
class SeleniumTestCase(StaticLiveServerTestCase):
|
|
||||||
"""
|
|
||||||
NB StaticLiveServerTestCase is used as the base test case so that
|
|
||||||
static files are served correctly in a Selenium test run context; see
|
|
||||||
https://docs.djangoproject.com/en/1.9/ref/contrib/staticfiles/#specialized-test-case-to-support-live-testing
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
""" Create a webdriver driver at the class level """
|
|
||||||
|
|
||||||
super(SeleniumTestCase, cls).setUpClass()
|
|
||||||
|
|
||||||
# instantiate the Selenium webdriver once for all the test methods
|
|
||||||
# in this test case
|
|
||||||
cls.driver = create_selenium_driver()
|
|
||||||
cls.driver.maximize_window()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
""" Clean up webdriver driver """
|
|
||||||
|
|
||||||
cls.driver.quit()
|
|
||||||
super(SeleniumTestCase, cls).tearDownClass()
|
|
||||||
|
|
||||||
def get(self, url):
|
|
||||||
"""
|
|
||||||
Selenium requires absolute URLs, so convert Django URLs returned
|
|
||||||
by resolve() or similar to absolute ones and get using the
|
|
||||||
webdriver instance.
|
|
||||||
|
|
||||||
url: a relative URL
|
|
||||||
"""
|
|
||||||
abs_url = '%s%s' % (self.live_server_url, url)
|
|
||||||
self.driver.get(abs_url)
|
|
||||||
|
|
||||||
def find(self, selector):
|
|
||||||
""" Find single element by CSS selector """
|
|
||||||
return self.driver.find_element_by_css_selector(selector)
|
|
||||||
|
|
||||||
def find_all(self, selector):
|
|
||||||
""" Find all elements matching CSS selector """
|
|
||||||
return self.driver.find_elements_by_css_selector(selector)
|
|
||||||
|
|
||||||
def element_exists(self, selector):
|
|
||||||
"""
|
|
||||||
Return True if one element matching selector exists,
|
|
||||||
False otherwise
|
|
||||||
"""
|
|
||||||
return len(self.find_all(selector)) == 1
|
|
||||||
|
|
||||||
def focused_element(self):
|
|
||||||
""" Return the element which currently has focus on the page """
|
|
||||||
return self.driver.switch_to.active_element
|
|
||||||
|
|
||||||
def wait_until_present(self, selector):
|
|
||||||
""" Wait until element matching CSS selector is on the page """
|
|
||||||
is_present = lambda driver: self.find(selector)
|
|
||||||
msg = 'An element matching "%s" should be on the page' % selector
|
|
||||||
element = Wait(self.driver).until(is_present, msg)
|
|
||||||
return element
|
|
||||||
|
|
||||||
def wait_until_visible(self, selector):
|
|
||||||
""" Wait until element matching CSS selector is visible on the page """
|
|
||||||
is_visible = lambda driver: self.find(selector).is_displayed()
|
|
||||||
msg = 'An element matching "%s" should be visible' % selector
|
|
||||||
Wait(self.driver).until(is_visible, msg)
|
|
||||||
return self.find(selector)
|
|
||||||
|
|
||||||
def wait_until_focused(self, selector):
|
|
||||||
""" Wait until element matching CSS selector has focus """
|
|
||||||
is_focused = \
|
|
||||||
lambda driver: self.find(selector) == self.focused_element()
|
|
||||||
msg = 'An element matching "%s" should be focused' % selector
|
|
||||||
Wait(self.driver).until(is_focused, msg)
|
|
||||||
return self.find(selector)
|
|
||||||
|
|
||||||
def enter_text(self, selector, value):
|
|
||||||
""" Insert text into element matching selector """
|
|
||||||
# note that keyup events don't occur until the element is clicked
|
|
||||||
# (in the case of <input type="text"...>, for example), so simulate
|
|
||||||
# user clicking the element before inserting text into it
|
|
||||||
field = self.click(selector)
|
|
||||||
|
|
||||||
field.send_keys(value)
|
|
||||||
return field
|
|
||||||
|
|
||||||
def click(self, selector):
|
|
||||||
""" Click on element which matches CSS selector """
|
|
||||||
element = self.wait_until_visible(selector)
|
|
||||||
element.click()
|
|
||||||
return element
|
|
||||||
|
|
||||||
def get_page_source(self):
|
|
||||||
""" Get raw HTML for the current page """
|
|
||||||
return self.driver.page_source
|
|
||||||
|
|||||||
Reference in New Issue
Block a user