diff --git a/doc/source/testing.rst b/doc/source/testing.rst index 30bf93b857..117e160bbc 100644 --- a/doc/source/testing.rst +++ b/doc/source/testing.rst @@ -19,7 +19,7 @@ before you submit any pull requests/patches. To run the tests:: $ ./run_tests.sh - + It's also possible to :doc:`run a subset of unit tests`. .. seealso:: @@ -27,6 +27,24 @@ It's also possible to :doc:`run a subset of unit tests`. :doc:`ref/run_tests` Full reference for the ``run_tests.sh`` script. + +By default running the Selenium tests will open your Firefox browser (you have +to install it first, else an error is raised), and you will be able to see the +tests actions. +If you want to run the suite headless, without being able to see them (as they +are ran on Jenkins), you can run the tests: + + $ ./run_tests.sh --with-selenium --selenium-headless + +Selenium will use a virtual display in this case, instead of your own. In order +to run the tests this way you have to install the dependency `xvfb`, like this: + + $ sudo apt-get install xvfb + +for a Debian OS flavour, or for Fedora/Red Hat flavours: + + $ sudo yum install xorg-x11-server-Xvfb + Writing tests ============= diff --git a/horizon/test/helpers.py b/horizon/test/helpers.py index 25fc544cb5..864e51a500 100644 --- a/horizon/test/helpers.py +++ b/horizon/test/helpers.py @@ -32,6 +32,7 @@ from django import test as django_test from django.test.client import RequestFactory # noqa from django.utils.encoding import force_unicode from django.utils import unittest +import xvfbwrapper LOG = logging.getLogger(__name__) @@ -169,6 +170,10 @@ class SeleniumTestCase(django_test.LiveServerTestCase): socket.setdefaulttimeout(60) if os.environ.get('WITH_SELENIUM', False): time.sleep(1) + # Start a virtual display server for running the tests headless. + if os.environ.get('SELENIUM_HEADLESS', False): + cls.vdisplay = xvfbwrapper.Xvfb(width=1280, height=720) + cls.vdisplay.start() cls.selenium = WebDriver() super(SeleniumTestCase, cls).setUpClass() @@ -177,6 +182,8 @@ class SeleniumTestCase(django_test.LiveServerTestCase): if os.environ.get('WITH_SELENIUM', False): cls.selenium.quit() time.sleep(1) + if hasattr(cls, 'vdisplay'): + cls.vdisplay.stop() super(SeleniumTestCase, cls).tearDownClass() def setUp(self): diff --git a/openstack_dashboard/test/integration_tests/helpers.py b/openstack_dashboard/test/integration_tests/helpers.py index 86b452645e..577f22cb49 100644 --- a/openstack_dashboard/test/integration_tests/helpers.py +++ b/openstack_dashboard/test/integration_tests/helpers.py @@ -15,6 +15,7 @@ import os import selenium from selenium.webdriver.support import ui import testtools +import xvfbwrapper from openstack_dashboard.test.integration_tests import config from openstack_dashboard.test.integration_tests.pages import loginpage @@ -24,6 +25,11 @@ class BaseTestCase(testtools.TestCase): def setUp(self): if os.environ.get('INTEGRATION_TESTS', False): + # Start a virtual display server for running the tests headless. + if os.environ.get('SELENIUM_HEADLESS', False): + self.vdisplay = xvfbwrapper.Xvfb(width=1280, height=720) + self.vdisplay.start() + # Start the Selenium webdriver and setup configuration. self.driver = selenium.webdriver.Firefox() self.conf = config.get_config() else: @@ -34,6 +40,8 @@ class BaseTestCase(testtools.TestCase): def tearDown(self): if os.environ.get('INTEGRATION_TESTS', False): self.driver.close() + if hasattr(self, 'vdisplay'): + self.vdisplay.stop() super(BaseTestCase, self).tearDown() def wait_for_title(self): diff --git a/run_tests.sh b/run_tests.sh index 1b054d5d4e..85fc110859 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -6,7 +6,7 @@ set -o errexit # Increment me any time the environment should be rebuilt. # This includes dependency changes, directory renames, etc. # Simple integer sequence: 1, 2, 3... -environment_version=42 +environment_version=43 #--------------------------------------------------------# function usage { @@ -33,6 +33,7 @@ function usage { echo " Implies -V if -N is not set." echo " --only-selenium Run only the Selenium unit tests" echo " --with-selenium Run unit tests including Selenium tests" + echo " --selenium-headless Run Selenium tests headless" echo " --integration Run the integration tests (requires a running " echo " OpenStack environment)" echo " --runserver Run the Django development server for" @@ -75,6 +76,7 @@ restore_env=0 runserver=0 only_selenium=0 with_selenium=0 +selenium_headless=0 integration=0 testopts="" testargs="" @@ -110,6 +112,7 @@ function process_option { --compilemessages) compilemessages=1;; --only-selenium) only_selenium=1;; --with-selenium) with_selenium=1;; + --selenium-headless) selenium_headless=1;; --integration) integration=1;; --docs) just_docs=1;; --runserver) runserver=1;; @@ -308,6 +311,10 @@ function run_tests { testopts="$testopts --exclude-dir=openstack_dashboard/test/integration_tests" fi + if [ $selenium_headless -eq 1 ]; then + export SELENIUM_HEADLESS=1 + fi + if [ -z "$testargs" ]; then run_tests_all else @@ -370,6 +377,10 @@ function run_tests_all { function run_integration_tests { export INTEGRATION_TESTS=1 + if [ $selenium_headless -eq 1 ]; then + export SELENIUM_HEADLESS=1 + fi + echo "Running Horizon integration tests..." if [ -z "$testargs" ]; then ${command_wrapper} nosetests openstack_dashboard/test/integration_tests/tests diff --git a/test-requirements.txt b/test-requirements.txt index 101f674474..ba692b2d75 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -13,3 +13,5 @@ oslosphinx selenium sphinx>=1.1.2,!=1.2.0,<1.3 testtools>=0.9.34 +# This also needs xvfb library installed on your OS +xvfbwrapper>=0.1.3