Adding integration test support
* Update test requirements for selenium testing * Add gate scripts * Add draft integration test config and test stub * Update tox for running integration tests The patch for the gate job: Change-Id: Ie6c8ee63afbda075298fdf2043990f5e9042308d
This commit is contained in:
parent
d9b7cc4b3a
commit
16370f1a13
|
@ -22,3 +22,7 @@ releasenotes/build/
|
|||
node_modules/
|
||||
npm-debug.log
|
||||
|
||||
*.pyc
|
||||
.tox
|
||||
.idea
|
||||
*.egg-info
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2010-2011 OpenStack Foundation
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 oslotest import base
|
||||
|
||||
|
||||
class TestCase(base.BaseTestCase):
|
||||
|
||||
"""Test case base class for all unit tests."""
|
|
@ -0,0 +1,79 @@
|
|||
#
|
||||
# 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=app_catalog.tests.integration_tests.pages
|
||||
plugin_page_structure={
|
||||
"Project":
|
||||
{
|
||||
"Catalog":
|
||||
{
|
||||
"_":
|
||||
[
|
||||
"Applications",
|
||||
"Components"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 openstack_dashboard.test.integration_tests.pages import basepage
|
||||
|
||||
|
||||
class ApplicationsPage(basepage.BaseNavigationPage):
|
||||
|
||||
def __init__(self, driver, conf):
|
||||
super(ApplicationsPage, self).__init__(driver, conf)
|
||||
self._page_title = "Application Catalog"
|
|
@ -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 openstack_dashboard.test.integration_tests.pages import basepage
|
||||
|
||||
|
||||
class ComponentsPage(basepage.BaseNavigationPage):
|
||||
|
||||
def __init__(self, driver, conf):
|
||||
super(ComponentsPage, self).__init__(driver, conf)
|
||||
self._page_title = "Components Catalog"
|
|
@ -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 TestApplications(helpers.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestApplications, self).setUp()
|
||||
self.home_pg.go_to_catalog_applicationspage()
|
||||
|
||||
def test_applications(self):
|
||||
self._save_screenshot(None)
|
||||
# TODO(markvan): Place holder for tests
|
||||
|
||||
def tearDown(self):
|
||||
super(TestApplications, self).tearDown()
|
|
@ -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 TestComponents(helpers.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestComponents, self).setUp()
|
||||
self.home_pg.go_to_catalog_componentspage()
|
||||
|
||||
def test_components(self):
|
||||
self._save_screenshot(None)
|
||||
# TODO(markvan): Place holder for tests
|
||||
|
||||
def tearDown(self):
|
||||
super(TestComponents, self).tearDown()
|
|
@ -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 = 'app_catalog.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',
|
||||
'app_catalog.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']['app_catalog_ui'] = {
|
||||
'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'
|
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
"""
|
||||
test_app_catalog_dashboard
|
||||
----------------------------------
|
||||
|
||||
Tests for `app_catalog_dashboard` module.
|
||||
"""
|
||||
|
||||
from app_catalog.tests import base
|
||||
|
||||
|
||||
class TestApp_Catalog_dashboard(base.TestCase):
|
||||
|
||||
def test_something(self):
|
||||
pass
|
|
@ -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))
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
pbr<2.0,>=1.3
|
|
@ -1,7 +1,24 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
# Hacking already pins down pep8, pyflakes and flake8
|
||||
hacking<0.11,>=0.10.0
|
||||
|
||||
# doc build requirements
|
||||
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
|
||||
http://tarballs.openstack.org/horizon/horizon-master.tar.gz#egg=horizon
|
||||
coverage>=3.6
|
||||
ddt>=1.0.1 # MIT
|
||||
discover
|
||||
django-nose>=1.2
|
||||
python-subunit>=0.0.18
|
||||
nose-exclude # LGPL
|
||||
selenium!=2.49,!=2.50 # Apache-2.0
|
||||
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
|
||||
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
|
||||
oslotest>=1.10.0 # Apache-2.0
|
||||
reno>=0.1.1 # Apache2
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=1.4.0
|
||||
# This also needs xvfb library installed on your OS
|
||||
xvfbwrapper!=0.2.8,>=0.1.3 #license: MIT
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
export APP_CATALOG_SCREENSHOTS_DIR=/opt/stack/new/app-catalog-ui/.tox/py27integration/src/horizon/openstack_dashboard/test/integration_tests/integration_tests_screenshots
|
|
@ -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/app-catalog-ui
|
||||
sudo -H -u stack tox -e py27integration
|
||||
retval=$?
|
||||
set -e
|
||||
|
||||
if [ -d ${APP_CATALOG_SCREENSHOTS_DIR}/ ]; then
|
||||
cp -r ${APP_CATALOG_SCREENSHOTS_DIR}/ /home/jenkins/workspace/gate-app-catalog-ui-dsvm-integration/
|
||||
fi
|
||||
exit $retval
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This script will be executed inside pre_test_hook function in devstack gate
|
||||
|
||||
set -ex
|
||||
source commons $@
|
22
tox.ini
22
tox.ini
|
@ -4,8 +4,19 @@ envlist = pep8,eslint
|
|||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
NOSE_WITH_OPENSTACK=1
|
||||
NOSE_OPENSTACK_COLOR=1
|
||||
NOSE_OPENSTACK_RED=0.05
|
||||
NOSE_OPENSTACK_YELLOW=0.025
|
||||
NOSE_OPENSTACK_SHOW_ELAPSED=1
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
whitelist_externals = /usr/bin/npm
|
||||
/bin/bash
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
|
@ -16,6 +27,15 @@ commands = flake8
|
|||
commands = npm install
|
||||
npm run lint
|
||||
|
||||
[testenv:py27integration]
|
||||
basepython = python2.7
|
||||
setenv =
|
||||
INTEGRATION_TESTS=1
|
||||
SELENIUM_HEADLESS=1
|
||||
HORIZON_INTEGRATION_TESTS_CONFIG_FILE=app_catalog/tests/integration_tests/horizon.conf
|
||||
DJANGO_SETTINGS_MODULE=app_catalog.tests.settings
|
||||
commands = nosetests app_catalog/tests/integration_tests/tests {posargs}
|
||||
|
||||
[testenv:releasenotes]
|
||||
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
|
||||
|
||||
|
|
Loading…
Reference in New Issue