Merge "Avoid duplicated maintenance of integration test config"
This commit is contained in:
commit
9724c7c58d
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,6 +25,7 @@ openstack_dashboard/local/*
|
|||||||
openstack_dashboard/local/local_settings.d/*
|
openstack_dashboard/local/local_settings.d/*
|
||||||
!openstack_dashboard/local/local_settings.d/*.example
|
!openstack_dashboard/local/local_settings.d/*.example
|
||||||
openstack_dashboard/test/.secret_key_store
|
openstack_dashboard/test/.secret_key_store
|
||||||
|
openstack_dashboard/test/integration_tests/horizon.conf.sample
|
||||||
openstack_dashboard/test/integration_tests/local-horizon.conf
|
openstack_dashboard/test/integration_tests/local-horizon.conf
|
||||||
openstack_dashboard/test/integration_tests/test_reports/
|
openstack_dashboard/test/integration_tests/test_reports/
|
||||||
openstack_dashboard/wsgi/horizon.wsgi
|
openstack_dashboard/wsgi/horizon.wsgi
|
||||||
|
@ -8,8 +8,16 @@ Running the integration tests
|
|||||||
|
|
||||||
#. Set up an OpenStack server
|
#. Set up an OpenStack server
|
||||||
|
|
||||||
#. Update the configuration file at `horizon.conf` or add overrides
|
#. Prepare the configuration file at `local-horizon.conf` if you need
|
||||||
to that file in `local-horizon.conf` which is ignored by git.
|
to change the default configurations.
|
||||||
|
Note that `horizon.conf` can be used for the same purpose too
|
||||||
|
from the historical reason.
|
||||||
|
|
||||||
|
You can generate a sample configuration file by the following command::
|
||||||
|
|
||||||
|
$ oslo-config-generator \
|
||||||
|
--namespace openstack_dashboard_integration_tests
|
||||||
|
--output-file openstack_dashboard/test/integration_tests/horizon.conf.sample
|
||||||
|
|
||||||
#. Run the tests. ::
|
#. Run the tests. ::
|
||||||
|
|
||||||
|
@ -18,45 +18,44 @@ from oslo_config import cfg
|
|||||||
DashboardGroup = [
|
DashboardGroup = [
|
||||||
cfg.StrOpt('dashboard_url',
|
cfg.StrOpt('dashboard_url',
|
||||||
default='http://localhost/dashboard/',
|
default='http://localhost/dashboard/',
|
||||||
help="Where the dashboard can be found"),
|
help='Where the dashboard can be found'),
|
||||||
cfg.StrOpt('help_url',
|
cfg.StrOpt('help_url',
|
||||||
default='https://docs.openstack.org/',
|
default='https://docs.openstack.org/',
|
||||||
help="Dashboard help page url"),
|
help='Dashboard help page url'),
|
||||||
]
|
]
|
||||||
|
|
||||||
IdentityGroup = [
|
IdentityGroup = [
|
||||||
cfg.StrOpt('username',
|
cfg.StrOpt('username',
|
||||||
default='demo',
|
default='demo',
|
||||||
help="Username to use for non-admin API requests."),
|
help='Username to use for non-admin API requests.'),
|
||||||
cfg.StrOpt('password',
|
cfg.StrOpt('password',
|
||||||
default='secretadmin',
|
default='secretadmin',
|
||||||
help="API key to use when authenticating.",
|
help='API key to use when authenticating.',
|
||||||
secret=True),
|
secret=True),
|
||||||
cfg.StrOpt('domain',
|
cfg.StrOpt('domain',
|
||||||
default=None,
|
default=None,
|
||||||
help="Domain name to use if required for login"),
|
help='Domain name to use if required for login'),
|
||||||
cfg.StrOpt('home_project',
|
cfg.StrOpt('home_project',
|
||||||
default='demo',
|
default='demo',
|
||||||
help="Project to keep all objects belonging to a regular user."
|
help='Project to keep all objects belonging to a regular user.'
|
||||||
),
|
),
|
||||||
cfg.StrOpt('admin_username',
|
cfg.StrOpt('admin_username',
|
||||||
default='admin',
|
default='admin',
|
||||||
help="Administrative Username to use for admin API "
|
help='Administrative Username to use for admin API requests.'),
|
||||||
"requests."),
|
|
||||||
cfg.StrOpt('admin_password',
|
cfg.StrOpt('admin_password',
|
||||||
default='secretadmin',
|
default='secretadmin',
|
||||||
help="API key to use when authenticating as admin.",
|
help='API key to use when authenticating as admin.',
|
||||||
secret=True),
|
secret=True),
|
||||||
cfg.StrOpt('admin_home_project',
|
cfg.StrOpt('admin_home_project',
|
||||||
default='admin',
|
default='admin',
|
||||||
help="Project to keep all objects belonging to an admin user."),
|
help='Project to keep all objects belonging to an admin user.'),
|
||||||
cfg.StrOpt('default_keystone_role',
|
cfg.StrOpt('default_keystone_role',
|
||||||
default='member',
|
default='member',
|
||||||
help="Name of default role every user gets in his new project"),
|
help='Name of default role every user gets in his new project.'),
|
||||||
cfg.StrOpt('default_keystone_admin_role',
|
cfg.StrOpt('default_keystone_admin_role',
|
||||||
default='admin',
|
default='admin',
|
||||||
help="Name of the role that grants admin rights to a user in "
|
help=('Name of the role that grants admin rights to a user in '
|
||||||
"his project"),
|
'his project')),
|
||||||
cfg.IntOpt('unique_last_password_count',
|
cfg.IntOpt('unique_last_password_count',
|
||||||
# The default value is chosen to match the value of
|
# The default value is chosen to match the value of
|
||||||
# [security_compliance] unique_last_password_count in DevStack
|
# [security_compliance] unique_last_password_count in DevStack
|
||||||
@ -65,10 +64,10 @@ IdentityGroup = [
|
|||||||
# in keystone may differ, so you might need
|
# in keystone may differ, so you might need
|
||||||
# to change this parameter.
|
# to change this parameter.
|
||||||
default=2,
|
default=2,
|
||||||
help=("The number of passwords for a user that must be unique "
|
help=('The number of passwords for a user that must be unique '
|
||||||
"before an old password can be used. "
|
'before an old password can be used. '
|
||||||
"This should match the keystone configuration option "
|
'This should match the keystone configuration option '
|
||||||
"'[security_compliance] unique_last_password_count'.")),
|
'"[security_compliance] unique_last_password_count".')),
|
||||||
]
|
]
|
||||||
|
|
||||||
ImageGroup = [
|
ImageGroup = [
|
||||||
@ -98,28 +97,38 @@ NetworkGroup = [
|
|||||||
|
|
||||||
AvailableServiceGroup = [
|
AvailableServiceGroup = [
|
||||||
cfg.BoolOpt('neutron',
|
cfg.BoolOpt('neutron',
|
||||||
default=True),
|
default=True,
|
||||||
|
help='Whether neutron is expected to be available'),
|
||||||
]
|
]
|
||||||
|
|
||||||
SeleniumGroup = [
|
SeleniumGroup = [
|
||||||
cfg.FloatOpt('message_implicit_wait',
|
cfg.FloatOpt(
|
||||||
default=0.1,
|
'message_implicit_wait',
|
||||||
help="Time to wait for confirmation modal in seconds"),
|
default=0.1,
|
||||||
cfg.IntOpt('implicit_wait',
|
help='Timeout in seconds to wait for message confirmation modal'),
|
||||||
default=10,
|
cfg.IntOpt(
|
||||||
help="Implicit wait timeout in seconds"),
|
'implicit_wait',
|
||||||
cfg.IntOpt('explicit_wait',
|
default=10,
|
||||||
default=90,
|
help=('Implicit timeout to wait until element become available, '
|
||||||
help="Explicit wait timeout in seconds"),
|
'It is used for every find_element, find_elements call.')),
|
||||||
cfg.IntOpt('page_timeout',
|
cfg.IntOpt(
|
||||||
default=60,
|
'explicit_wait',
|
||||||
help="Page load timeout in seconds"),
|
default=90,
|
||||||
cfg.StrOpt('screenshots_directory',
|
help=('Explicit timeout is used for long lasting operations, '
|
||||||
default="integration_tests_screenshots",
|
'Methods using explicit timeout are usually prefixed with '
|
||||||
help="Output screenshot directory"),
|
'"wait"')),
|
||||||
cfg.BoolOpt('maximize_browser',
|
cfg.IntOpt(
|
||||||
default=True,
|
'page_timeout',
|
||||||
help="Is the browser size maximized for each test?"),
|
default=60,
|
||||||
|
help='Timeout in seconds to wait for a page to become available'),
|
||||||
|
cfg.StrOpt(
|
||||||
|
'screenshots_directory',
|
||||||
|
default='integration_tests_screenshots',
|
||||||
|
help='Output directory for screenshots'),
|
||||||
|
cfg.BoolOpt(
|
||||||
|
'maximize_browser',
|
||||||
|
default=True,
|
||||||
|
help='Maximize the browser window at the start of each test or not'),
|
||||||
]
|
]
|
||||||
|
|
||||||
FlavorsGroup = [
|
FlavorsGroup = [
|
||||||
@ -137,13 +146,13 @@ ScenarioGroup = [
|
|||||||
InstancesGroup = [
|
InstancesGroup = [
|
||||||
cfg.StrOpt('available_zone',
|
cfg.StrOpt('available_zone',
|
||||||
default='nova',
|
default='nova',
|
||||||
help="Zone to be selected for launch Instances"),
|
help='Availability zone to be selected for launch instances'),
|
||||||
cfg.StrOpt('image_name',
|
cfg.StrOpt('image_name',
|
||||||
default='cirros-0.4.0-x86_64-disk (12.1 MB)',
|
default='cirros-0.4.0-x86_64-disk (12.1 MB)',
|
||||||
help="Boot Source to be selected for launch Instances"),
|
help='Boot Source to be selected for launch Instances'),
|
||||||
cfg.StrOpt('flavor',
|
cfg.StrOpt('flavor',
|
||||||
default='m1.tiny',
|
default='m1.tiny',
|
||||||
help="Flavor to be selected for launch Instances"),
|
help='Flavor to be selected for launch instances'),
|
||||||
]
|
]
|
||||||
|
|
||||||
VolumeGroup = [
|
VolumeGroup = [
|
||||||
@ -156,14 +165,18 @@ VolumeGroup = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
PluginGroup = [
|
PluginGroup = [
|
||||||
cfg.BoolOpt('is_plugin',
|
cfg.BoolOpt(
|
||||||
default='False',
|
'is_plugin',
|
||||||
help="Set to true if this is a plugin"),
|
default='False',
|
||||||
cfg.MultiStrOpt('plugin_page_path',
|
help='Set to true if this is a plugin'),
|
||||||
default='',
|
cfg.MultiStrOpt(
|
||||||
help='Additional path to look for plugin page content'),
|
'plugin_page_path',
|
||||||
cfg.MultiStrOpt('plugin_page_structure',
|
default='',
|
||||||
default='')
|
help='Additional path to look for plugin page content'),
|
||||||
|
cfg.MultiStrOpt(
|
||||||
|
'plugin_page_structure',
|
||||||
|
default='',
|
||||||
|
help=('JSON string to define the page structure for the plugin')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -172,13 +185,11 @@ def _get_config_files():
|
|||||||
os.path.abspath(os.path.dirname(os.path.dirname(__file__))),
|
os.path.abspath(os.path.dirname(os.path.dirname(__file__))),
|
||||||
'integration_tests')
|
'integration_tests')
|
||||||
conf_file = os.environ.get('HORIZON_INTEGRATION_TESTS_CONFIG_FILE',
|
conf_file = os.environ.get('HORIZON_INTEGRATION_TESTS_CONFIG_FILE',
|
||||||
"%s/horizon.conf" % conf_dir)
|
'%s/horizon.conf' % conf_dir)
|
||||||
config_files = [conf_file]
|
|
||||||
local_config = os.environ.get('HORIZON_INTEGRATION_TESTS_LOCAL_CONFIG',
|
local_config = os.environ.get('HORIZON_INTEGRATION_TESTS_LOCAL_CONFIG',
|
||||||
"%s/local-horizon.conf" % conf_dir)
|
'%s/local-horizon.conf' % conf_dir)
|
||||||
if os.path.isfile(local_config):
|
config_files = [conf_file, local_config]
|
||||||
config_files.append(local_config)
|
return [f for f in config_files if os.path.isfile(f)]
|
||||||
return config_files
|
|
||||||
|
|
||||||
|
|
||||||
def get_config():
|
def get_config():
|
||||||
@ -197,3 +208,19 @@ def get_config():
|
|||||||
cfg.CONF.register_opts(VolumeGroup, group="volume")
|
cfg.CONF.register_opts(VolumeGroup, group="volume")
|
||||||
|
|
||||||
return cfg.CONF
|
return cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
def list_opts():
|
||||||
|
return [
|
||||||
|
("dashboard", DashboardGroup),
|
||||||
|
("selenium", SeleniumGroup),
|
||||||
|
("flavors", FlavorsGroup),
|
||||||
|
("image", ImageGroup),
|
||||||
|
("identity", IdentityGroup),
|
||||||
|
("network", NetworkGroup),
|
||||||
|
("service_available", AvailableServiceGroup),
|
||||||
|
("scenario", ScenarioGroup),
|
||||||
|
("launch_instances", InstancesGroup),
|
||||||
|
("plugin", PluginGroup),
|
||||||
|
("volume", VolumeGroup),
|
||||||
|
]
|
||||||
|
@ -54,6 +54,7 @@ add_comments = Translators:
|
|||||||
[entry_points]
|
[entry_points]
|
||||||
oslo.config.opts =
|
oslo.config.opts =
|
||||||
openstack_dashboard = openstack_dashboard.utils.config:list_options
|
openstack_dashboard = openstack_dashboard.utils.config:list_options
|
||||||
|
openstack_dashboard_integration_tests = openstack_dashboard.test.integration_tests.config:list_opts
|
||||||
# We use a custom extractor to find translatable strings in AngularJS templates.
|
# We use a custom extractor to find translatable strings in AngularJS templates.
|
||||||
# See http://babel.pocoo.org/docs/messages/#referencing-extraction-methods for
|
# See http://babel.pocoo.org/docs/messages/#referencing-extraction-methods for
|
||||||
# details on how this works.
|
# details on how this works.
|
||||||
|
4
tox.ini
4
tox.ini
@ -88,7 +88,9 @@ setenv =
|
|||||||
PYTHONHASHSEED=0
|
PYTHONHASHSEED=0
|
||||||
INTEGRATION_TESTS=1
|
INTEGRATION_TESTS=1
|
||||||
SELENIUM_HEADLESS=1
|
SELENIUM_HEADLESS=1
|
||||||
commands = {envpython} {toxinidir}/manage.py test openstack_dashboard --settings=openstack_dashboard.test.settings --verbosity 2 --tag integration {posargs}
|
commands =
|
||||||
|
oslo-config-generator --namespace openstack_dashboard_integration_tests
|
||||||
|
{envpython} {toxinidir}/manage.py test openstack_dashboard --settings=openstack_dashboard.test.settings --verbosity 2 --tag integration {posargs}
|
||||||
|
|
||||||
[testenv:npm]
|
[testenv:npm]
|
||||||
passenv =
|
passenv =
|
||||||
|
Loading…
Reference in New Issue
Block a user