[Toaster] [PATCH] toaster/tests: browser add class SeleniumTestCaseBase
Smith, Elliot
elliot.smith at intel.com
Fri Jul 15 03:33:03 PDT 2016
Thanks.
Added to toaster-next and sent upstream to bitbake-devel.
Elliot
On 14 July 2016 at 16:56, Aníbal Limón <anibal.limon at linux.intel.com> wrote:
> In order to reuse selenium helper outside django environment,
> add a new module with base class SeleniumTestCaseBase only
> with inherit of unittest.TestCase for reuse selenium helper
> in functional testing of Toaster outside django environment.
>
> Add class SeleniumTestCase with multiple inherit of
> StaticLiveServerTestCase and SeleniumTestCaseBase for don't
> broke things.
>
> Signed-off-by: Aníbal Limón <anibal.limon at linux.intel.com>
> ---
> .../lib/toaster/tests/browser/selenium_helpers.py | 187
> +-----------------
> .../toaster/tests/browser/selenium_helpers_base.py | 216
> +++++++++++++++++++++
> 2 files changed, 221 insertions(+), 182 deletions(-)
> create mode 100644
> bitbake/lib/toaster/tests/browser/selenium_helpers_base.py
>
> diff --git a/bitbake/lib/toaster/tests/browser/selenium_helpers.py
> b/bitbake/lib/toaster/tests/browser/selenium_helpers.py
> index ef07858..ddb43fd 100644
> --- a/bitbake/lib/toaster/tests/browser/selenium_helpers.py
> +++ b/bitbake/lib/toaster/tests/browser/selenium_helpers.py
> @@ -23,195 +23,18 @@
> # modified from Patchwork, released under the same licence terms as
> Toaster:
> #
> https://github.com/dlespiau/patchwork/blob/master/patchwork/tests.browser.py
>
> +from django.contrib.staticfiles.testing import StaticLiveServerTestCase
> +from tests.browser.selenium_helpers_base import SeleniumTestCaseBase
> +
> """
> Helper methods for creating Toaster Selenium tests which run within
> the context of Django unit tests.
> """
>
> -import os
> -import time
> -
> -from django.contrib.staticfiles.testing import StaticLiveServerTestCase
> -from selenium import webdriver
> -from selenium.webdriver.support.ui import WebDriverWait
> -from selenium.webdriver.common.desired_capabilities import
> DesiredCapabilities
> -from selenium.common.exceptions import NoSuchElementException, \
> - StaleElementReferenceException, TimeoutException
> -
> -def create_selenium_driver(browser='chrome'):
> - # set default browser string based on env (if available)
> - 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 == 'marionette':
> - capabilities = DesiredCapabilities.FIREFOX
> - capabilities['marionette'] = True
> - return webdriver.Firefox(capabilities=capabilities)
> - 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):
> +class SeleniumTestCase(SeleniumTestCaseBase, 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
> + pass
> diff --git a/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py
> b/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py
> new file mode 100644
> index 0000000..c4161d7
> --- /dev/null
> +++ b/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py
> @@ -0,0 +1,216 @@
> +#! /usr/bin/env python
> +# ex:ts=4:sw=4:sts=4:et
> +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
> +#
> +# BitBake Toaster Implementation
> +#
> +# Copyright (C) 2013-2016 Intel Corporation
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License version 2 as
> +# published by the Free Software Foundation.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License along
> +# with this program; if not, write to the Free Software Foundation, Inc.,
> +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> +#
> +# The Wait class and some of SeleniumDriverHelper and SeleniumTestCase are
> +# modified from Patchwork, released under the same licence terms as
> Toaster:
> +#
> https://github.com/dlespiau/patchwork/blob/master/patchwork/tests.browser.py
> +
> +"""
> +Base helper methods for creating Toaster Selenium tests.
> +"""
> +
> +import os
> +import time
> +import unittest
> +
> +from selenium import webdriver
> +from selenium.webdriver.support.ui import WebDriverWait
> +from selenium.webdriver.common.desired_capabilities import
> DesiredCapabilities
> +from selenium.common.exceptions import NoSuchElementException, \
> + StaleElementReferenceException, TimeoutException
> +
> +def create_selenium_driver(browser='chrome'):
> + # set default browser string based on env (if available)
> + 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 == 'marionette':
> + capabilities = DesiredCapabilities.FIREFOX
> + capabilities['marionette'] = True
> + return webdriver.Firefox(capabilities=capabilities)
> + 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 SeleniumTestCaseBase(unittest.TestCase):
> + """
> + 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(SeleniumTestCaseBase, 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(SeleniumTestCaseBase, 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
> --
> 2.1.4
>
>
--
Elliot Smith
Software Engineer
Intel Open Source Technology Centre
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.yoctoproject.org/pipermail/toaster/attachments/20160715/977e5f84/attachment-0001.html>
More information about the toaster
mailing list