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
|
||||
|
||||
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
|
||||
===================================
|
||||
|
||||
|
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.
|
||||
# This includes dependency changes, directory renames, etc.
|
||||
# Simple integer sequence: 1, 2, 3...
|
||||
environment_version=41
|
||||
environment_version=42
|
||||
#--------------------------------------------------------#
|
||||
|
||||
function usage {
|
||||
@ -32,6 +32,8 @@ 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 " --integration Run the integration tests (requires a running "
|
||||
echo " OpenStack environment)"
|
||||
echo " --runserver Run the Django development server for"
|
||||
echo " openstack_dashboard in the virtual"
|
||||
echo " environment."
|
||||
@ -71,6 +73,7 @@ restore_env=0
|
||||
runserver=0
|
||||
only_selenium=0
|
||||
with_selenium=0
|
||||
integration=0
|
||||
testopts=""
|
||||
testargs=""
|
||||
with_coverage=0
|
||||
@ -104,6 +107,7 @@ function process_option {
|
||||
--compilemessages) compilemessages=1;;
|
||||
--only-selenium) only_selenium=1;;
|
||||
--with-selenium) with_selenium=1;;
|
||||
--integration) integration=1;;
|
||||
--docs) just_docs=1;;
|
||||
--runserver) runserver=1;;
|
||||
--backup-environment) backup_env=1;;
|
||||
@ -351,6 +355,14 @@ function run_tests_all {
|
||||
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 {
|
||||
OPTS="-l en --no-obsolete"
|
||||
DASHBOARD_OPTS="--extension=html,txt,csv --ignore=openstack/common/*"
|
||||
@ -465,6 +477,12 @@ if [ $just_tabs -eq 1 ]; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Integration tests
|
||||
if [ $integration -eq 1 ]; then
|
||||
run_integration_tests
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Django development server
|
||||
if [ $runserver -eq 1 ]; then
|
||||
run_server
|
||||
|
@ -15,3 +15,4 @@ sphinx>=1.1.2,<1.2
|
||||
# for bug 1091333, remove after sphinx >1.1.3 is released.
|
||||
docutils==0.9.1
|
||||
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
|
||||
/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]
|
||||
downloadcache = ~/cache/pip
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user