From e221f7482a19642bd0649fd87c1d44ae7d0bbc9b Mon Sep 17 00:00:00 2001 From: Mark Vanderwiel Date: Tue, 2 Feb 2016 11:53:13 -0600 Subject: [PATCH] Adding integration test support * Update requirements for selenium testing * Add gate scripts * Add draft integration test config and test stub * Update tox for running integration tests A patch for gate job is: I76ab460a110d93b0186ca126858f79ac9e89f09b Change-Id: I5ca1bf7003a9882648cdfbeab21d2ada37b951f1 --- .../tests/integration_tests/__init__.py | 0 .../tests/integration_tests/horizon.conf | 78 ++++++++ .../tests/integration_tests/pages/__init__.py | 0 .../pages/project/__init__.py | 0 .../pages/project/network/__init__.py | 0 .../project/network/loadbalancerspage.py | 22 ++ .../tests/integration_tests/tests/__init__.py | 0 .../tests/test_loadbalancers.py | 27 +++ neutron_lbaas_dashboard/tests/settings.py | 188 ++++++++++++++++++ neutron_lbaas_dashboard/tests/urls.py | 20 ++ test-requirements.txt | 5 + tools/gate/integration/commons | 5 + tools/gate/integration/post_test_hook.sh | 17 ++ tools/gate/integration/pre_test_hook.sh | 28 +++ tox.ini | 10 + 15 files changed, 400 insertions(+) create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/__init__.py create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/horizon.conf create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/pages/__init__.py create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/pages/project/__init__.py create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/__init__.py create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/loadbalancerspage.py create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/tests/__init__.py create mode 100644 neutron_lbaas_dashboard/tests/integration_tests/tests/test_loadbalancers.py create mode 100644 neutron_lbaas_dashboard/tests/settings.py create mode 100644 neutron_lbaas_dashboard/tests/urls.py create mode 100644 tools/gate/integration/commons create mode 100755 tools/gate/integration/post_test_hook.sh create mode 100755 tools/gate/integration/pre_test_hook.sh diff --git a/neutron_lbaas_dashboard/tests/integration_tests/__init__.py b/neutron_lbaas_dashboard/tests/integration_tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/neutron_lbaas_dashboard/tests/integration_tests/horizon.conf b/neutron_lbaas_dashboard/tests/integration_tests/horizon.conf new file mode 100644 index 00000000..ce22ea3b --- /dev/null +++ b/neutron_lbaas_dashboard/tests/integration_tests/horizon.conf @@ -0,0 +1,78 @@ +# +# Configuration filed based on Tempest's tempest.conf.sample +# + +[dashboard] +# Where the dashboard can be found (string value) +dashboard_url=http://localhost/dashboard/ + +# Login page for the dashboard (string value) +login_url=http://localhost/dashboard/auth/login/ + +# Dashboard help page url (string value) +help_url=http://docs.openstack.org/ + +[selenium] +# Timeout in seconds to wait for a page to become available +# (integer value) +page_timeout=30 + +# Output directory for screenshots. +# (string value) +screenshots_directory=integration_tests_screenshots + +# Implicit timeout to wait until element become available, +# this timeout is used for every find_element, find_elements call. +# (integer value) +implicit_wait=10 + +# Explicit timeout is used for long lasting operations, +# methods using explicit timeout are usually prefixed with 'wait', +# those methods ignore implicit_wait when looking up web elements. +# (integer value) +explicit_wait=300 + +[image] +# http accessible image (string value) +http_image=http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz + +[identity] +# Username to use for non-admin API requests. (string value) +username=demo + +# API key to use when authenticating. (string value) +password=secretadmin + +# 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=secretadmin + +[scenario] +# ssh username for image file (string value) +ssh_user=cirros + +[launch_instances] +#available zone to launch instances +available_zone=nova +#image_name to launch instances +image_name=cirros-0.3.4-x86_64-uec (24.0 MB) + +[plugin] + +is_plugin=True +plugin_page_path=neutron_lbaas_dashboard.tests.integration_tests.pages +plugin_page_structure={ + "Project": + { + "Network": + { + "-": + [ + "Load Balancers" + ] + } + } + } diff --git a/neutron_lbaas_dashboard/tests/integration_tests/pages/__init__.py b/neutron_lbaas_dashboard/tests/integration_tests/pages/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/neutron_lbaas_dashboard/tests/integration_tests/pages/project/__init__.py b/neutron_lbaas_dashboard/tests/integration_tests/pages/project/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/__init__.py b/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/loadbalancerspage.py b/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/loadbalancerspage.py new file mode 100644 index 00000000..4c6c5802 --- /dev/null +++ b/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/loadbalancerspage.py @@ -0,0 +1,22 @@ +# 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. + +from openstack_dashboard.test.integration_tests.pages import basepage + + +class LoadbalancersPage(basepage.BaseNavigationPage): + + TABLE_IMAGE_COLUMN = 'name' + + def __init__(self, driver, conf): + super(LoadbalancersPage, self).__init__(driver, conf) + self._page_title = "Load Balancers" diff --git a/neutron_lbaas_dashboard/tests/integration_tests/tests/__init__.py b/neutron_lbaas_dashboard/tests/integration_tests/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/neutron_lbaas_dashboard/tests/integration_tests/tests/test_loadbalancers.py b/neutron_lbaas_dashboard/tests/integration_tests/tests/test_loadbalancers.py new file mode 100644 index 00000000..1d36c866 --- /dev/null +++ b/neutron_lbaas_dashboard/tests/integration_tests/tests/test_loadbalancers.py @@ -0,0 +1,27 @@ +# 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. + +from openstack_dashboard.test.integration_tests import helpers + + +class TestLoadbalancers(helpers.TestCase): + + def setUp(self): + super(TestLoadbalancers, self).setUp() + self.home_pg.go_to_network_loadbalancerspage() + + def test_loadbalancers(self): + self._save_screenshot(None) + # TODO(MRV): Place holder for tests + + def tearDown(self): + super(TestLoadbalancers, self).tearDown() diff --git a/neutron_lbaas_dashboard/tests/settings.py b/neutron_lbaas_dashboard/tests/settings.py new file mode 100644 index 00000000..cb507443 --- /dev/null +++ b/neutron_lbaas_dashboard/tests/settings.py @@ -0,0 +1,188 @@ +# +# 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 importlib +import os +import six + +from horizon.test.settings import * # noqa +from horizon.utils import secret_key +from openstack_dashboard import exceptions + + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +TEST_DIR = os.path.dirname(os.path.abspath(__file__)) +ROOT_PATH = os.path.abspath(os.path.join(TEST_DIR, "..")) + +MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media')) +MEDIA_URL = '/media/' +STATIC_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'static')) +STATIC_URL = '/static/' + +SECRET_KEY = secret_key.generate_or_read_from_file( + os.path.join(TEST_DIR, '.secret_key_store')) +ROOT_URLCONF = 'neutron_lbaas_dashboard.tests.urls' +TEMPLATE_DIRS = ( + os.path.join(TEST_DIR, 'templates'), +) + +TEMPLATE_CONTEXT_PROCESSORS += ( + 'openstack_dashboard.context_processors.openstack', +) + +INSTALLED_APPS = ( + 'django.contrib.contenttypes', + 'django.contrib.auth', + 'django.contrib.sessions', + 'django.contrib.staticfiles', + 'django.contrib.messages', + 'django.contrib.humanize', + 'django_nose', + 'openstack_auth', + 'compressor', + 'horizon', + 'openstack_dashboard', + 'openstack_dashboard.dashboards', +) + +AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',) + +SITE_BRANDING = 'OpenStack' + +HORIZON_CONFIG = { + "password_validator": { + "regex": '^.{8,18}$', + "help_text": "Password must be between 8 and 18 characters." + }, + 'user_home': None, + 'help_url': "http://docs.openstack.org", + 'exceptions': {'recoverable': exceptions.RECOVERABLE, + 'not_found': exceptions.NOT_FOUND, + 'unauthorized': exceptions.UNAUTHORIZED}, + 'angular_modules': [], + 'js_files': [], +} + +# Load the pluggable dashboard settings +from openstack_dashboard.utils import settings +dashboard_module_names = [ + 'openstack_dashboard.enabled', + 'openstack_dashboard.local.enabled', + 'neutron_lbaas_dashboard.enabled', +] +dashboard_modules = [] +# All dashboards must be enabled for the namespace to get registered, which is +# needed by the unit tests. +for module_name in dashboard_module_names: + module = importlib.import_module(module_name) + dashboard_modules.append(module) + for submodule in six.itervalues(settings.import_submodules(module)): + if getattr(submodule, 'DISABLED', None): + delattr(submodule, 'DISABLED') +INSTALLED_APPS = list(INSTALLED_APPS) # Make sure it's mutable +settings.update_dashboards(dashboard_modules, HORIZON_CONFIG, INSTALLED_APPS) + + +# Set to True to allow users to upload images to glance via Horizon server. +# When enabled, a file form field will appear on the create image form. +# See documentation for deployment considerations. +HORIZON_IMAGES_ALLOW_UPLOAD = True + +AVAILABLE_REGIONS = [ + ('http://localhost:5000/v2.0', 'local'), + ('http://remote:5000/v2.0', 'remote'), +] + +OPENSTACK_API_VERSIONS = { + "identity": 3 +} + +OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v2.0" +OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_" + +OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True +OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'test_domain' + +OPENSTACK_KEYSTONE_BACKEND = { + 'name': 'native', + 'can_edit_user': True, + 'can_edit_group': True, + 'can_edit_project': True, + 'can_edit_domain': True, + 'can_edit_role': True +} + +OPENSTACK_CINDER_FEATURES = { + 'enable_backup': True, +} + +OPENSTACK_NEUTRON_NETWORK = { + 'enable_lb': False, + 'enable_firewall': False, + 'enable_vpn': False +} + +OPENSTACK_HYPERVISOR_FEATURES = { + 'can_set_mount_point': True, + + # NOTE: as of Grizzly this is not yet supported in Nova so enabling this + # setting will not do anything useful + 'can_encrypt_volumes': False +} + +LOGGING['loggers']['openstack_dashboard'] = { + 'handlers': ['test'], + 'propagate': False, +} + +LOGGING['loggers']['selenium'] = { + 'handlers': ['test'], + 'propagate': False, +} + +LOGGING['loggers']['neutron_lbaas_dashboard'] = { + 'handlers': ['test'], + 'propagate': False, +} + +SECURITY_GROUP_RULES = { + 'all_tcp': { + 'name': 'ALL TCP', + 'ip_protocol': 'tcp', + 'from_port': '1', + 'to_port': '65535', + }, + 'http': { + 'name': 'HTTP', + 'ip_protocol': 'tcp', + 'from_port': '80', + 'to_port': '80', + }, +} + +NOSE_ARGS = ['--nocapture', + '--nologcapture', + '--cover-package=openstack_dashboard', + '--cover-inclusive', + '--all-modules'] + +POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf") +POLICY_FILES = { + 'identity': 'keystone_policy.json', + 'compute': 'nova_policy.json' +} + +# The openstack_auth.user.Token object isn't JSON-serializable ATM +SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' diff --git a/neutron_lbaas_dashboard/tests/urls.py b/neutron_lbaas_dashboard/tests/urls.py new file mode 100644 index 00000000..9bef20ff --- /dev/null +++ b/neutron_lbaas_dashboard/tests/urls.py @@ -0,0 +1,20 @@ +# +# 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. + +from django.conf import urls +import openstack_dashboard.urls + +urlpatterns = urls.patterns( + '', + urls.url(r'', urls.include(openstack_dashboard.urls)) +) diff --git a/test-requirements.txt b/test-requirements.txt index 79285a75..13c2c852 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -6,12 +6,17 @@ hacking<0.11,>=0.10.0 http://tarballs.openstack.org/horizon/horizon-master.tar.gz#egg=horizon coverage>=3.6 # Apache-2.0 +ddt>=1.0.1 # MIT discover # BSD django-nose>=1.2 # BSD python-subunit>=0.0.18 # Apache-2.0/BSD +nose-exclude # LGPL +selenium>=2.50.1 # Apache-2.0 sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 oslotest>=1.10.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=1.4.0 # MIT +# This also needs xvfb library installed on your OS +xvfbwrapper>=0.1.3 #license: MIT diff --git a/tools/gate/integration/commons b/tools/gate/integration/commons new file mode 100644 index 00000000..1f2fe43b --- /dev/null +++ b/tools/gate/integration/commons @@ -0,0 +1,5 @@ +#!/bin/bash + +set -ex + +export LBAAS_DASHBOARD_SCREENSHOTS_DIR=/opt/stack/new/neutron-lbaas-dashboard/.tox/py27integration/src/horizon/openstack_dashboard/test/integration_tests/integration_tests_screenshots diff --git a/tools/gate/integration/post_test_hook.sh b/tools/gate/integration/post_test_hook.sh new file mode 100755 index 00000000..0f9cbf87 --- /dev/null +++ b/tools/gate/integration/post_test_hook.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# This script will be executed inside post_test_hook function in devstack gate + +set -x +source commons $@ + +set +e +cd /opt/stack/new/neutron-lbaas-dashboard +sudo -H -u stack tox -e py27integration +retval=$? +set -e + +if [ -d ${NEUTRON_LBAAS_DASHBOARD_SCREENSHOTS_DIR}/ ]; then + cp -r ${NEUTRON_LBAAS_DASHBOARD_SCREENSHOTS_DIR}/ /home/jenkins/workspace/gate-neutron-lbaas-dashboard-dsvm-integration/ +fi +exit $retval diff --git a/tools/gate/integration/pre_test_hook.sh b/tools/gate/integration/pre_test_hook.sh new file mode 100755 index 00000000..4fb15a1f --- /dev/null +++ b/tools/gate/integration/pre_test_hook.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# This script will be executed inside pre_test_hook function in devstack gate + +set -ex +source commons $@ + +# Enable LBaaS V2 Neutron plugin +DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin neutron-lbaas https://git.openstack.org/openstack/neutron-lbaas" +ENABLED_SERVICES+=",q-lbaasv2" +DISABLED_SERVICES+="q-lbaas" + +# Enable default recommended implementation for LBaaS v2, Octavia +ENABLED_SERVICES+=",octavia,o-cw,o-hk,o-hm,o-api" +DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin octavia https://git.openstack.org/openstack/octavia" +DEVSTACK_LOCAL_CONFIG+=$'\n'"[[post-config|/etc/octavia/octavia.conf]]" +DEVSTACK_LOCAL_CONFIG+=$'\n'"[controller_worker]" +DEVSTACK_LOCAL_CONFIG+=$'\n'"amphora_driver = amphora_noop_driver" +DEVSTACK_LOCAL_CONFIG+=$'\n'"compute_driver = compute_noop_driver" +DEVSTACK_LOCAL_CONFIG+=$'\n'"network_driver = network_noop_driver" + +# Enable LBaaS v2 Horizon plugin +DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin neutron-lbaas-dashboard https://git.openstack.org/openstack/neutron-lbaas-dashboard" + +export DEVSTACK_LOCAL_CONFIG +export ENABLED_SERVICES +export DISABLED_SERVICES + diff --git a/tox.ini b/tox.ini index 5cf65e0b..7f2edb5f 100644 --- a/tox.ini +++ b/tox.ini @@ -16,6 +16,7 @@ setenv = deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt whitelist_externals = /usr/bin/npm + /bin/bash commands = python manage.py test [testenv:pep8] @@ -24,6 +25,15 @@ commands = flake8 [testenv:venv] commands = {posargs} +[testenv:py27integration] +basepython = python2.7 +setenv = + INTEGRATION_TESTS=1 + SELENIUM_HEADLESS=1 + HORIZON_INTEGRATION_TESTS_CONFIG_FILE=neutron_lbaas_dashboard/tests/integration_tests/horizon.conf + DJANGO_SETTINGS_MODULE=neutron_lbaas_dashboard.tests.settings +commands = nosetests neutron_lbaas_dashboard/tests/integration_tests/tests {posargs} + [testenv:cover] commands = python setup.py test --coverage --testr-args='{posargs}'