Add script to copy neutron api tests from tempest

This change adds a script to automate the copying of api tests from
tempest in the style of oslo_incubator.  The target path will be
neutron/tests/tempest and no manual modifications should be made to
this path until such time as neutron api test development is frozen in
tempest and development can proceed in the neutron tree.  Until that
occurs, a policy of manual once-daily synchronization is suggested.

The target path includes the name 'tempest' as a clear indication that
this is not part of neutron, and that once development is allowed to
proceed, its contents should be rewritten and removed until there is
nothing left.

So long as the tests exist in both the tempest and neutron trees,
testing effort will be duplicated.  The larger goal is to have the
tests in question removed from tempest as per the qa guidelines [1],
so this should be temporary.

1: https://wiki.openstack.org/wiki/QA/Tempest-test-removal

Change-Id: I3cd55983e610a1d61aae565f88fe5017edba1090
This commit is contained in:
Maru Newby 2015-02-21 00:15:12 +00:00
parent aeae583fa5
commit 30c6f56365
11 changed files with 257 additions and 22 deletions

View File

@ -138,6 +138,12 @@ to install and configure all of Neutron's package dependencies. It is
not necessary to provide this option if devstack has already been used
to deploy Neutron to the target host.
To run the api tests against a live Neutron daemon, deploy tempest and
neutron with devstack and then run the following commands: ::
export TEMPEST_CONFIG_DIR=/opt/stack/tempest/etc
tox -e api
For more information on the standard Tox-based test infrastructure used by
OpenStack and how to do some common test/debugging procedures with Testr,
see this wiki page:

View File

@ -0,0 +1,37 @@
# 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 unittest
# Allow the retargetable and tempest api tests to be executed as part
# of the same job by ensuring that tests from both tests are
# discovered.
#
# TODO(marun) Remove once the tempest tests have been moved to api/
def _discover(loader, path, pattern):
return loader.discover(path, pattern=pattern, top_level_dir=".")
def load_tests(_, tests, pattern):
suite = unittest.TestSuite()
suite.addTests(tests)
loader = unittest.loader.TestLoader()
suite.addTests(_discover(loader, "./neutron/tests/api", pattern))
suite.addTests(_discover(loader,
"./neutron/tests/tempest/api/network",
pattern))
return suite

View File

@ -0,0 +1,5 @@
This path contains artifacts from tempest that have been modified to
support the execution of api tests from the neutron tree. These
artifacts are intended to be a stop-gap to support test migration, and
it is hoped that changes to tempest and tempest-lib will render it
unnecessary at some point in the future.

View File

View File

@ -0,0 +1,116 @@
# Copyright 2012 OpenStack Foundation
# All Rights Reserved.
#
# 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 neutron.openstack.common import log as logging
from neutron.tests.tempest.common import cred_provider
from neutron.tests.tempest import config
from neutron.tests.tempest import manager
from neutron.tests.tempest.services.identity.v2.json.identity_client import \
IdentityClientJSON
from neutron.tests.tempest.services.identity.v2.json.token_client import \
TokenClientJSON
from neutron.tests.tempest.services.identity.v3.json.credentials_client \
import CredentialsClientJSON
from neutron.tests.tempest.services.identity.v3.json.endpoints_client import \
EndPointClientJSON
from neutron.tests.tempest.services.identity.v3.json.identity_client import \
IdentityV3ClientJSON
from neutron.tests.tempest.services.identity.v3.json.policy_client import \
PolicyClientJSON
from neutron.tests.tempest.services.identity.v3.json.region_client import \
RegionClientJSON
from neutron.tests.tempest.services.identity.v3.json.service_client import \
ServiceClientJSON
from neutron.tests.tempest.services.identity.v3.json.token_client import \
V3TokenClientJSON
from neutron.tests.tempest.services.network.json.network_client import \
NetworkClientJSON
CONF = config.CONF
LOG = logging.getLogger(__name__)
class Manager(manager.Manager):
"""
Top level manager for OpenStack tempest clients
"""
default_params = {
'disable_ssl_certificate_validation':
CONF.identity.disable_ssl_certificate_validation,
'ca_certs': CONF.identity.ca_certificates_file,
'trace_requests': CONF.debug.trace_requests
}
# NOTE: Tempest uses timeout values of compute API if project specific
# timeout values don't exist.
default_params_with_timeout_values = {
'build_interval': CONF.compute.build_interval,
'build_timeout': CONF.compute.build_timeout
}
default_params_with_timeout_values.update(default_params)
def __init__(self, credentials=None, service=None):
super(Manager, self).__init__(credentials=credentials)
self._set_identity_clients()
self.network_client = NetworkClientJSON(
self.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**self.default_params)
def _set_identity_clients(self):
params = {
'service': CONF.identity.catalog_type,
'region': CONF.identity.region,
'endpoint_type': 'adminURL'
}
params.update(self.default_params_with_timeout_values)
self.identity_client = IdentityClientJSON(self.auth_provider,
**params)
self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider,
**params)
self.endpoints_client = EndPointClientJSON(self.auth_provider,
**params)
self.service_client = ServiceClientJSON(self.auth_provider, **params)
self.policy_client = PolicyClientJSON(self.auth_provider, **params)
self.region_client = RegionClientJSON(self.auth_provider, **params)
self.credentials_client = CredentialsClientJSON(self.auth_provider,
**params)
self.token_client = TokenClientJSON()
if CONF.identity_feature_enabled.api_v3:
self.token_v3_client = V3TokenClientJSON()
class AdminManager(Manager):
"""
Manager object that uses the admin credentials for its
managed client objects
"""
def __init__(self, service=None):
super(AdminManager, self).__init__(
credentials=cred_provider.get_configured_credentials(
'identity_admin'),
service=service)

View File

@ -18,12 +18,11 @@ This module implements BaseNeutronClient for the Tempest rest client
and configures the api tests with scenarios targeting the Neutron API.
"""
from tempest import test as t_test
from tempest_lib import exceptions
import testscenarios
from neutron.tests.api import base_v2
from neutron.tests.tempest import test as t_test
# Required to generate tests from scenarios. Not compatible with nose.
load_tests = testscenarios.load_tests_apply_scenarios

View File

@ -21,39 +21,25 @@ function generate_testr_results {
fi
}
function dsvm_functional_prep_func {
:
}
function api_prep_func {
sudo chown -R $owner:stack $TEMPEST_DIR
sudo -H -u $owner tox -e $venv --notest
sudo -H -u $owner .tox/$venv/bin/pip install -e $TEMPEST_DIR
}
if [ "$venv" == "dsvm-functional" ]
then
owner=stack
prep_func="dsvm_functional_prep_func"
sudo_env=
elif [ "$venv" == "api" ]
then
owner=tempest
prep_func="api_prep_func"
# Configure the api tests to use the tempest.conf set by devstack.
sudo_env="TEMPEST_CONFIG_DIR=$TEMPEST_DIR/etc"
fi
# Set owner permissions according to job's requirements.
cd $NEUTRON_DIR
sudo chown -R $owner:stack $NEUTRON_DIR
# Prep the environment according to job's requirements.
$prep_func
# Run tests
echo "Running neutron $venv test suite"
set +e
sudo -H -u $owner tox -e $venv
sudo -H -u $owner $sudo_env tox -e $venv
testr_exit_code=$?
set -e

View File

@ -0,0 +1,6 @@
WARNING
=======
The files under this path are maintained automatically by the script
tools/copy_api_tests_from_tempest.sh. It's contents should not be
manually modified until further notice.

View File

@ -0,0 +1,77 @@
#!/bin/bash
# This script is intended to allow repeatable migration of the neutron
# api tests from tempest. The intention is to allow development to
# continue in Tempest while the migration strategy evolves.
set -e
if [[ "$#" -ne 1 ]]; then
>&2 echo "Usage: $0 /path/to/tempest
Migrate neutron's api tests from a tempest repo."
exit 1
fi
TEMPEST_PATH=${TEMPEST_PATH:-$1}
if [ ! -f "$TEMPEST_PATH/run_tempest.sh" ]; then
>&2 echo "Unable to find tempest at '$TEMPEST_PATH'. Please verify that the specified path points to a valid tempest repo."
exit 1
fi
NEUTRON_PATH=${NEUTRON_PATH:-$(cd $(dirname "$0")/.. && pwd)}
NEUTRON_TEST_PATH=$NEUTRON_PATH/neutron/tests
function copy_files {
local tempest_dep_paths=(
'tempest'
'tempest/api/network'
'tempest/api/network/admin'
'tempest/common'
'tempest/common/generator'
'tempest/common/utils'
'tempest/services'
'tempest/services/identity'
'tempest/services/identity/v3'
'tempest/services/identity/v3/json'
'tempest/services/network'
'tempest/services/network/json'
)
for tempest_dep_path in ${tempest_dep_paths[@]}; do
local target_path=$NEUTRON_TEST_PATH/$tempest_dep_path
if [[ ! -d "$target_path" ]]; then
mkdir -p $target_path
fi
cp $TEMPEST_PATH/$tempest_dep_path/*.py $target_path
done
touch $NEUTRON_TEST_PATH/tempest/api/__init__.py
local paths_to_remove=(
"$NEUTRON_TEST_PATH/tempest/clients.py"
)
for path_to_remove in ${paths_to_remove[@]}; do
if [ -f "$path_to_remove" ]; then
rm ${path_to_remove}
fi
done
}
function rewrite_imports {
regexes=(
's/tempest.common.generator/neutron.tests.tempest.common.generator/'
's/tempest.test/neutron.tests.tempest.test/'
's/from tempest.openstack.common import lockutils/from oslo_concurrency import lockutils/'
's/from tempest.openstack.common import importutils/from oslo_utils import importutils/'
's/tempest.openstack.common/neutron.openstack.common/'
's/from tempest(?!_lib) import clients/from neutron.tests.api.contrib import clients/'
's/from tempest(?!_lib)/from neutron.tests.tempest/'
's/CONF.lock_path/CONF.oslo_concurrency.lock_path/'
)
files=$(find $NEUTRON_TEST_PATH/tempest -name '*.py')
for ((i = 0; i < ${#regexes[@]}; i++)); do
perl -p -i -e "${regexes[$i]}" $files
done
}
copy_files
rewrite_imports

View File

@ -32,7 +32,7 @@ check_opinionated_shell () {
# If you cannot avoid the use of bash, please change the EXPECTED var below.
OBSERVED=$(grep -E '^([[:space:]]*[^#[:space:]]|#!).*bash' \
tox.ini tools/* | wc -l)
EXPECTED=6
EXPECTED=7
if [ ${EXPECTED} -ne ${OBSERVED} ]; then
echo "Bash usage has been detected!" >>$FAILURES
fi

View File

@ -84,7 +84,10 @@ commands = sphinx-build -W -b html doc/source doc/build
ignore = E125,E126,E128,E129,E265,H305,H404,H405
show-source = true
builtins = _
exclude = ./.*,build,dist,neutron/openstack/common/*
# neutron/tests/tempest needs to be excluded so long as it continues
# to be copied directly from tempest, since tempest and neutron do not
# share a flake8 configuration.
exclude = ./.*,build,dist,neutron/openstack/common/*,neutron/tests/tempest
[hacking]
import_exceptions = neutron.i18n