Integration tests - running the tests
Initial setup for running the integration tests. A basic test is included to ensure this works, although it will be rewritten to follow the Page Object pattern. Thanks to Daniel Korn for the initial test. https://wiki.openstack.org/wiki/Horizon/Testing/UI Implements blueprint: selenium-integration-testing Change-Id: Id5b62cdeac5295667a3922f7bed1db3c7617f841
This commit is contained in:
parent
990f151cdc
commit
b4b0e1a887
@ -70,6 +70,21 @@ To run just the `WorkflowsTests.test_workflow_view` test method::
|
|||||||
|
|
||||||
./run_tests.sh horizon.test.tests.workflows:WorkflowsTests.test_workflow_view
|
./run_tests.sh horizon.test.tests.workflows:WorkflowsTests.test_workflow_view
|
||||||
|
|
||||||
|
Running the integration tests
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
The Horizon integration tests treat Horizon as a black box, and similar
|
||||||
|
to Tempest must be run against an existing OpenStack system. These
|
||||||
|
tests are not run by default.
|
||||||
|
|
||||||
|
#. Update the configuration file
|
||||||
|
`openstack_dashboard/test/integration_tests/horizon.conf` as
|
||||||
|
required (the format is similar to the Tempest configuration file).
|
||||||
|
|
||||||
|
#. Run the tests with the following command: ::
|
||||||
|
|
||||||
|
$ ./run_tests.sh --integration
|
||||||
|
|
||||||
Using Dashboard and Panel Templates
|
Using Dashboard and Panel Templates
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
22
openstack_dashboard/test/integration_tests/README.rst
Normal file
22
openstack_dashboard/test/integration_tests/README.rst
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Horizon Integration Tests
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Horizon's integration tests treat Horizon as a black box.
|
||||||
|
|
||||||
|
Running the integration tests
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
#. Set up an OpenStack server
|
||||||
|
|
||||||
|
#. Update the configuration file at `horizon.conf`
|
||||||
|
|
||||||
|
#. Run the tests. ::
|
||||||
|
|
||||||
|
$ ./run_tests.sh --integration
|
||||||
|
|
||||||
|
More information
|
||||||
|
----------------
|
||||||
|
|
||||||
|
https://wiki.openstack.org/wiki/Horizon/Testing/UI
|
||||||
|
|
||||||
|
https://wiki.mozilla.org/QA/Execution/Web_Testing/Docs/Automation/StyleGuide#Page_Objects
|
66
openstack_dashboard/test/integration_tests/config.py
Normal file
66
openstack_dashboard/test/integration_tests/config.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
|
||||||
|
DashboardGroup = [
|
||||||
|
cfg.StrOpt('dashboard_url',
|
||||||
|
default='http://localhost/',
|
||||||
|
help="Where the dashboard can be found"),
|
||||||
|
cfg.StrOpt('login_url',
|
||||||
|
default='http://localhost/auth/login/',
|
||||||
|
help="Login page for the dashboard"),
|
||||||
|
cfg.IntOpt('page_timeout',
|
||||||
|
default=10,
|
||||||
|
help="Timeout in seconds"),
|
||||||
|
]
|
||||||
|
|
||||||
|
IdentityGroup = [
|
||||||
|
cfg.StrOpt('username',
|
||||||
|
default='demo',
|
||||||
|
help="Username to use for non-admin API requests."),
|
||||||
|
cfg.StrOpt('password',
|
||||||
|
default='pass',
|
||||||
|
help="API key to use when authenticating.",
|
||||||
|
secret=True),
|
||||||
|
cfg.StrOpt('admin_username',
|
||||||
|
default='admin',
|
||||||
|
help="Administrative Username to use for admin API "
|
||||||
|
"requests."),
|
||||||
|
cfg.StrOpt('admin_password',
|
||||||
|
default='pass',
|
||||||
|
help="API key to use when authenticating as admin.",
|
||||||
|
secret=True),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _get_config_files():
|
||||||
|
conf_dir = os.path.join(
|
||||||
|
os.path.abspath(os.path.dirname(os.path.dirname(__file__))),
|
||||||
|
'integration_tests')
|
||||||
|
conf_file = os.environ.get('HORIZON_INTEGRATION_TESTS_CONFIG_FILE',
|
||||||
|
"%s/horizon.conf" % conf_dir)
|
||||||
|
return [conf_file]
|
||||||
|
|
||||||
|
|
||||||
|
def get_config():
|
||||||
|
cfg.CONF([], project='horizon', default_config_files=_get_config_files())
|
||||||
|
|
||||||
|
cfg.CONF.register_opts(DashboardGroup, group="dashboard")
|
||||||
|
cfg.CONF.register_opts(IdentityGroup, group="identity")
|
||||||
|
|
||||||
|
return cfg.CONF
|
43
openstack_dashboard/test/integration_tests/helpers.py
Normal file
43
openstack_dashboard/test/integration_tests/helpers.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import selenium
|
||||||
|
from selenium.webdriver.support import ui
|
||||||
|
import testtools
|
||||||
|
|
||||||
|
from openstack_dashboard.test.integration_tests import config
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTestCase(testtools.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
if os.environ.get('INTEGRATION_TESTS', False):
|
||||||
|
self.driver = selenium.webdriver.Firefox()
|
||||||
|
self.conf = config.get_config()
|
||||||
|
else:
|
||||||
|
msg = "The INTEGRATION_TESTS env variable is not set."
|
||||||
|
raise self.skipException(msg)
|
||||||
|
super(BaseTestCase, self).setUp()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
if os.environ.get('INTEGRATION_TESTS', False):
|
||||||
|
self.driver.close()
|
||||||
|
super(BaseTestCase, self).tearDown()
|
||||||
|
|
||||||
|
def wait_for_title(self):
|
||||||
|
timeout = self.conf.dashboard.page_timeout
|
||||||
|
ui.WebDriverWait(self.driver, timeout).until(lambda d:
|
||||||
|
self.driver.title)
|
28
openstack_dashboard/test/integration_tests/horizon.conf
Normal file
28
openstack_dashboard/test/integration_tests/horizon.conf
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#
|
||||||
|
# Configuration filed based on Tempest's tempest.conf.sample
|
||||||
|
#
|
||||||
|
|
||||||
|
[dashboard]
|
||||||
|
# Where the dashboard can be found (string value)
|
||||||
|
dashboard_url=http://localhost/
|
||||||
|
|
||||||
|
# Login page for the dashboard (string value)
|
||||||
|
login_url=http://localhost/auth/login/
|
||||||
|
|
||||||
|
# Timeout in seconds to wait for a page to become available
|
||||||
|
# (integer value)
|
||||||
|
page_timeout=10
|
||||||
|
|
||||||
|
[identity]
|
||||||
|
# Username to use for non-admin API requests. (string value)
|
||||||
|
username=demo
|
||||||
|
|
||||||
|
# API key to use when authenticating. (string value)
|
||||||
|
password=pass
|
||||||
|
|
||||||
|
# Administrative Username to use for admin API requests.
|
||||||
|
# (string value)
|
||||||
|
admin_username=admin
|
||||||
|
|
||||||
|
# API key to use when authenticating as admin. (string value)
|
||||||
|
admin_password=pass
|
@ -0,0 +1,43 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import selenium.webdriver.common.keys as keys
|
||||||
|
|
||||||
|
from openstack_dashboard.test.integration_tests import helpers
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoginPage(helpers.BaseTestCase):
|
||||||
|
"""This is a basic scenario test:
|
||||||
|
* checks that the login page is available
|
||||||
|
* logs in as a regular user
|
||||||
|
* checks that the user home page loads without error
|
||||||
|
|
||||||
|
FIXME(jpichon): This test will be rewritten using the Page Objects
|
||||||
|
pattern, which is much more maintainable.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_login(self):
|
||||||
|
self.driver.get(self.conf.dashboard.login_url)
|
||||||
|
self.assertIn("Login", self.driver.title)
|
||||||
|
|
||||||
|
username = self.driver.find_element_by_name("username")
|
||||||
|
password = self.driver.find_element_by_name("password")
|
||||||
|
|
||||||
|
username.send_keys(self.conf.identity.username)
|
||||||
|
password.send_keys(self.conf.identity.password)
|
||||||
|
username.send_keys(keys.Keys.RETURN)
|
||||||
|
|
||||||
|
self.wait_for_title()
|
||||||
|
self.assertIn("Instance Overview", self.driver.title)
|
20
run_tests.sh
20
run_tests.sh
@ -6,7 +6,7 @@ set -o errexit
|
|||||||
# Increment me any time the environment should be rebuilt.
|
# Increment me any time the environment should be rebuilt.
|
||||||
# This includes dependency changes, directory renames, etc.
|
# This includes dependency changes, directory renames, etc.
|
||||||
# Simple integer sequence: 1, 2, 3...
|
# Simple integer sequence: 1, 2, 3...
|
||||||
environment_version=41
|
environment_version=42
|
||||||
#--------------------------------------------------------#
|
#--------------------------------------------------------#
|
||||||
|
|
||||||
function usage {
|
function usage {
|
||||||
@ -32,6 +32,8 @@ function usage {
|
|||||||
echo " Implies -V if -N is not set."
|
echo " Implies -V if -N is not set."
|
||||||
echo " --only-selenium Run only the Selenium unit tests"
|
echo " --only-selenium Run only the Selenium unit tests"
|
||||||
echo " --with-selenium Run unit tests including Selenium tests"
|
echo " --with-selenium Run unit tests including Selenium tests"
|
||||||
|
echo " --integration Run the integration tests (requires a running "
|
||||||
|
echo " OpenStack environment)"
|
||||||
echo " --runserver Run the Django development server for"
|
echo " --runserver Run the Django development server for"
|
||||||
echo " openstack_dashboard in the virtual"
|
echo " openstack_dashboard in the virtual"
|
||||||
echo " environment."
|
echo " environment."
|
||||||
@ -71,6 +73,7 @@ restore_env=0
|
|||||||
runserver=0
|
runserver=0
|
||||||
only_selenium=0
|
only_selenium=0
|
||||||
with_selenium=0
|
with_selenium=0
|
||||||
|
integration=0
|
||||||
testopts=""
|
testopts=""
|
||||||
testargs=""
|
testargs=""
|
||||||
with_coverage=0
|
with_coverage=0
|
||||||
@ -104,6 +107,7 @@ function process_option {
|
|||||||
--compilemessages) compilemessages=1;;
|
--compilemessages) compilemessages=1;;
|
||||||
--only-selenium) only_selenium=1;;
|
--only-selenium) only_selenium=1;;
|
||||||
--with-selenium) with_selenium=1;;
|
--with-selenium) with_selenium=1;;
|
||||||
|
--integration) integration=1;;
|
||||||
--docs) just_docs=1;;
|
--docs) just_docs=1;;
|
||||||
--runserver) runserver=1;;
|
--runserver) runserver=1;;
|
||||||
--backup-environment) backup_env=1;;
|
--backup-environment) backup_env=1;;
|
||||||
@ -351,6 +355,14 @@ function run_tests_all {
|
|||||||
exit $TEST_RESULT
|
exit $TEST_RESULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function run_integration_tests {
|
||||||
|
export INTEGRATION_TESTS=1
|
||||||
|
|
||||||
|
echo "Running Horizon integration tests..."
|
||||||
|
${command_wrapper} nosetests openstack_dashboard/test/integration_tests/tests
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
function run_makemessages {
|
function run_makemessages {
|
||||||
OPTS="-l en --no-obsolete"
|
OPTS="-l en --no-obsolete"
|
||||||
DASHBOARD_OPTS="--extension=html,txt,csv --ignore=openstack/common/*"
|
DASHBOARD_OPTS="--extension=html,txt,csv --ignore=openstack/common/*"
|
||||||
@ -465,6 +477,12 @@ if [ $just_tabs -eq 1 ]; then
|
|||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Integration tests
|
||||||
|
if [ $integration -eq 1 ]; then
|
||||||
|
run_integration_tests
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
|
||||||
# Django development server
|
# Django development server
|
||||||
if [ $runserver -eq 1 ]; then
|
if [ $runserver -eq 1 ]; then
|
||||||
run_server
|
run_server
|
||||||
|
@ -15,3 +15,4 @@ sphinx>=1.1.2,<1.2
|
|||||||
# for bug 1091333, remove after sphinx >1.1.3 is released.
|
# for bug 1091333, remove after sphinx >1.1.3 is released.
|
||||||
docutils==0.9.1
|
docutils==0.9.1
|
||||||
oslo.sphinx
|
oslo.sphinx
|
||||||
|
testtools>=0.9.34
|
||||||
|
8
tox.ini
8
tox.ini
@ -30,6 +30,14 @@ basepython = python2.7
|
|||||||
commands = pip install django==1.4
|
commands = pip install django==1.4
|
||||||
/bin/bash run_tests.sh -N --no-pep8
|
/bin/bash run_tests.sh -N --no-pep8
|
||||||
|
|
||||||
|
[testenv:py27integration]
|
||||||
|
basepython = python2.7
|
||||||
|
commands = /bin/bash run_tests.sh -N --integration
|
||||||
|
|
||||||
|
[testenv:py26integration]
|
||||||
|
basepython = python2.6
|
||||||
|
commands = /bin/bash run_tests.sh -N --integration
|
||||||
|
|
||||||
[tox:jenkins]
|
[tox:jenkins]
|
||||||
downloadcache = ~/cache/pip
|
downloadcache = ~/cache/pip
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user