From cc62587035ad1dc6e765b4c5cf15dd847f8b9e7a Mon Sep 17 00:00:00 2001 From: "Yuanbin.Chen" Date: Thu, 18 Jan 2018 09:56:28 +0800 Subject: [PATCH] Add basic functional tests This patch add openstack client call, use openstack client execute profile, policy, cluster, node, receiver, action, event list operation. Change-Id: I7f2a60c276f82ad9afab8130fea73fde078eff07 Signed-off-by: Yuanbin.Chen --- .testr.conf | 2 +- .../senlinclient-dsvm-functional/run.yaml | 4 +- senlinclient/tests/functional/base.py | 39 ++++++++++++++++++ .../functional/{ => hooks}/post_test_hook.sh | 15 ++++--- .../functional/{ => hooks}/pre_test_hook.sh | 0 senlinclient/tests/functional/test_actions.py | 24 +++++++++++ .../tests/functional/test_clusters.py | 41 +++++++++++++++++++ senlinclient/tests/functional/test_events.py | 24 +++++++++++ senlinclient/tests/functional/test_help.py | 22 ++++++++++ senlinclient/tests/functional/test_nodes.py | 25 +++++++++++ .../tests/functional/test_policies.py | 23 +++++++++++ .../tests/functional/test_policy_types.py | 35 ++++++++++++++++ .../tests/functional/test_profile_types.py | 40 ++++++++++++++++++ .../tests/functional/test_profiles.py | 23 +++++++++++ .../tests/functional/test_readonly_senlin.py | 24 +++++++++++ .../tests/functional/test_receivers.py | 24 +++++++++++ senlinclient/tests/functional/test_version.py | 20 +++++++++ test-requirements.txt | 2 + tox.ini | 8 ++++ 19 files changed, 386 insertions(+), 9 deletions(-) create mode 100644 senlinclient/tests/functional/base.py rename senlinclient/tests/functional/{ => hooks}/post_test_hook.sh (76%) rename senlinclient/tests/functional/{ => hooks}/pre_test_hook.sh (100%) create mode 100644 senlinclient/tests/functional/test_actions.py create mode 100644 senlinclient/tests/functional/test_clusters.py create mode 100644 senlinclient/tests/functional/test_events.py create mode 100644 senlinclient/tests/functional/test_help.py create mode 100644 senlinclient/tests/functional/test_nodes.py create mode 100644 senlinclient/tests/functional/test_policies.py create mode 100644 senlinclient/tests/functional/test_policy_types.py create mode 100644 senlinclient/tests/functional/test_profile_types.py create mode 100644 senlinclient/tests/functional/test_profiles.py create mode 100644 senlinclient/tests/functional/test_readonly_senlin.py create mode 100644 senlinclient/tests/functional/test_receivers.py create mode 100644 senlinclient/tests/functional/test_version.py diff --git a/.testr.conf b/.testr.conf index a2ff14b2..fa9d34a6 100644 --- a/.testr.conf +++ b/.testr.conf @@ -1,4 +1,4 @@ [DEFAULT] -test_command=${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION +test_command=${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./senlinclient/tests/unit} $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list diff --git a/playbooks/legacy/senlinclient-dsvm-functional/run.yaml b/playbooks/legacy/senlinclient-dsvm-functional/run.yaml index b81037ae..63cd379d 100644 --- a/playbooks/legacy/senlinclient-dsvm-functional/run.yaml +++ b/playbooks/legacy/senlinclient-dsvm-functional/run.yaml @@ -52,13 +52,13 @@ fi function pre_test_hook { - cd /opt/stack/new/python-senlinclient/senlinclient/tests/functional/ + cd /opt/stack/new/python-senlinclient/senlinclient/tests/functional/hooks/ ./pre_test_hook.sh } export -f pre_test_hook function post_test_hook { - cd /opt/stack/new/python-senlinclient/senlinclient/tests/functional/ + cd /opt/stack/new/python-senlinclient/senlinclient/tests/functional/hooks/ ./post_test_hook.sh } export -f post_test_hook diff --git a/senlinclient/tests/functional/base.py b/senlinclient/tests/functional/base.py new file mode 100644 index 00000000..b2e23029 --- /dev/null +++ b/senlinclient/tests/functional/base.py @@ -0,0 +1,39 @@ +# 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 tempest.lib.cli import base +from tempest.lib.cli import output_parser + + +class OpenStackClientTestBase(base.ClientTestBase): + """Command line client base functions.""" + + def setUp(self): + super(OpenStackClientTestBase, self).setUp() + self.parser = output_parser + + def _get_clients(self): + cli_dir = os.environ.get( + 'OS_SENLINCLIENT_EXEC_DIR', + os.path.join(os.path.abspath('.'), '.tox/functional/bin')) + + return base.CLIClient( + username=os.environ.get('OS_USERNAME'), + password=os.environ.get('OS_PASSWORD'), + tenant_name=os.environ.get('OS_TENANT_NAME'), + uri=os.environ.get('OS_AUTH_URL'), + cli_dir=cli_dir) + + def openstack(self, *args, **kwargs): + return self.clients.openstack(*args, **kwargs) diff --git a/senlinclient/tests/functional/post_test_hook.sh b/senlinclient/tests/functional/hooks/post_test_hook.sh similarity index 76% rename from senlinclient/tests/functional/post_test_hook.sh rename to senlinclient/tests/functional/hooks/post_test_hook.sh index d8d3e6ea..378a3439 100755 --- a/senlinclient/tests/functional/post_test_hook.sh +++ b/senlinclient/tests/functional/hooks/post_test_hook.sh @@ -16,17 +16,20 @@ export SENLINCLIENT_DIR="$BASE/new/python-senlinclient" -cd $BASE/new/devstack -source openrc admin admin +source $BASE/new/devstack/openrc admin admin + +cd $SENLINCLIENT_DIR + +sudo -E chown -R $USER:stack $SENLINCLIENT_DIR # Run tests echo "Running senlinclient functional test." set +e -# TODO(Anyone): Running senlinclient functional test by running -# "tox -efunctional" +sudo -E -H -u $USER tox -efunctional +RESULT=$? set -e -echo "Running senlinclient functional test succeeded." +echo "Completed running senlinclient functional test." -exit 0 +exit $RESULT diff --git a/senlinclient/tests/functional/pre_test_hook.sh b/senlinclient/tests/functional/hooks/pre_test_hook.sh similarity index 100% rename from senlinclient/tests/functional/pre_test_hook.sh rename to senlinclient/tests/functional/hooks/pre_test_hook.sh diff --git a/senlinclient/tests/functional/test_actions.py b/senlinclient/tests/functional/test_actions.py new file mode 100644 index 00000000..7752276f --- /dev/null +++ b/senlinclient/tests/functional/test_actions.py @@ -0,0 +1,24 @@ +# 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 senlinclient.tests.functional import base + + +class ActionTest(base.OpenStackClientTestBase): + """Test for actions""" + + def test_action_list(self): + result = self.openstack('cluster action list') + action_list = self.parser.listing(result) + self.assertTableStruct(action_list, ['id', 'name', 'action', 'status', + 'target_id', 'depends_on', + 'depended_by', 'created_at']) diff --git a/senlinclient/tests/functional/test_clusters.py b/senlinclient/tests/functional/test_clusters.py new file mode 100644 index 00000000..b49ae963 --- /dev/null +++ b/senlinclient/tests/functional/test_clusters.py @@ -0,0 +1,41 @@ +# 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 senlinclient.tests.functional import base + + +class ClusterTest(base.OpenStackClientTestBase): + """Test for clusters""" + + def test_cluster_list(self): + result = self.openstack('cluster list') + cluster_list = self.parser.listing(result) + self.assertTableStruct(cluster_list, ['id', 'name', 'status', + 'created_at', 'updated_at']) + + def test_cluster_list_filters(self): + params = {'name': 'test1', 'status': 'ACTIVE'} + for k, v in params.items(): + cmd = ('cluster list --filters %s=%s' % (k, v)) + self.openstack(cmd) + + def test_cluster_list_sort(self): + params = ['name', 'status', 'init_at', 'created_at', 'updated_at'] + for param in params: + cmd = 'cluster list --sort %s' % param + self.openstack(cmd) + + def test_cluster_full_id(self): + self.openstack('cluster list --full-id') + + def test_cluster_limit(self): + self.openstack('cluster list --limit 1') diff --git a/senlinclient/tests/functional/test_events.py b/senlinclient/tests/functional/test_events.py new file mode 100644 index 00000000..4fdeedc2 --- /dev/null +++ b/senlinclient/tests/functional/test_events.py @@ -0,0 +1,24 @@ +# 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 senlinclient.tests.functional import base + + +class EventTest(base.OpenStackClientTestBase): + """Test for events""" + + def test_event_list(self): + result = self.openstack('cluster event list') + event_list = self.parser.listing(result) + self.assertTableStruct(event_list, ['id', 'generated_at', 'obj_type', + 'obj_id', 'obj_name', 'action', + 'status', 'level', 'cluster_id']) diff --git a/senlinclient/tests/functional/test_help.py b/senlinclient/tests/functional/test_help.py new file mode 100644 index 00000000..f2775f62 --- /dev/null +++ b/senlinclient/tests/functional/test_help.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 senlinclient.tests.functional import base + + +class HelpTest(base.OpenStackClientTestBase): + """Test for help commands""" + + def test_help_cmd(self): + help_text = self.openstack('help cluster list') + lines = help_text.split('\n') + self.assertFirstLineStartsWith(lines, 'usage: openstack cluster list') diff --git a/senlinclient/tests/functional/test_nodes.py b/senlinclient/tests/functional/test_nodes.py new file mode 100644 index 00000000..f0025159 --- /dev/null +++ b/senlinclient/tests/functional/test_nodes.py @@ -0,0 +1,25 @@ +# 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 senlinclient.tests.functional import base + + +class NodeTest(base.OpenStackClientTestBase): + """Test for nodes""" + + def test_node_list(self): + result = self.openstack('cluster node list') + node_list = self.parser.listing(result) + self.assertTableStruct(node_list, ['id', 'name', 'index', 'status', + 'cluster_id', 'physical_id', + 'profile_name', 'created_at', + 'updated_at']) diff --git a/senlinclient/tests/functional/test_policies.py b/senlinclient/tests/functional/test_policies.py new file mode 100644 index 00000000..0656afa8 --- /dev/null +++ b/senlinclient/tests/functional/test_policies.py @@ -0,0 +1,23 @@ +# 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 senlinclient.tests.functional import base + + +class PolicyTest(base.OpenStackClientTestBase): + """Test for policies""" + + def test_policy_list(self): + result = self.openstack('cluster policy list') + policy_list = self.parser.listing(result) + self.assertTableStruct(policy_list, ['id', 'name', 'type', + 'created_at']) diff --git a/senlinclient/tests/functional/test_policy_types.py b/senlinclient/tests/functional/test_policy_types.py new file mode 100644 index 00000000..e09f4760 --- /dev/null +++ b/senlinclient/tests/functional/test_policy_types.py @@ -0,0 +1,35 @@ +# 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 senlinclient.tests.functional import base + + +class PolicyTypeTest(base.OpenStackClientTestBase): + """Test for policy types""" + + def test_policy_type_list(self): + result = self.openstack('cluster policy type list') + policy_type = self.parser.listing(result) + self.assertTableStruct(policy_type, ['name', 'version', + 'support_status']) + + def test_policy_type_show(self): + params = ['senlin.policy.affinity-1.0', + 'senlin.policy.batch-1.0', + 'senlin.policy.deletion-1.0', + 'senlin.policy.health-1.0', + 'senlin.policy.loadbalance-1.1', + 'senlin.policy.region_placement-1.0', + 'senlin.policy.zone_placement-1.0'] + for param in params: + cmd = 'cluster policy type show %s' % param + self.openstack(cmd) diff --git a/senlinclient/tests/functional/test_profile_types.py b/senlinclient/tests/functional/test_profile_types.py new file mode 100644 index 00000000..0044dfb3 --- /dev/null +++ b/senlinclient/tests/functional/test_profile_types.py @@ -0,0 +1,40 @@ +# 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 senlinclient.tests.functional import base + + +class ProfileTypeTest(base.OpenStackClientTestBase): + """Test for profile types + + Basic smoke test for the Openstack CLI commands which do not require + creating or modifying. + """ + def test_profile_type_list(self): + result = self.openstack('cluster profile type list') + profile_type = self.parser.listing(result) + self.assertTableStruct(profile_type, ['name', 'version', + 'support_status']) + + def test_profile_list_debug(self): + self.openstack('cluster profile list', flags='--debug') + + def test_profile_type_show(self): + params = ['container.dockerinc.docker-1.0', + 'os.heat.stack-1.0', + 'os.nova.server-1.0'] + for param in params: + cmd = 'cluster profile type show %s' % param + self.openstack(cmd) + + def test_profile_type_show_json(self): + self.openstack('cluster profile type show os.nova.server-1.0 -f json') diff --git a/senlinclient/tests/functional/test_profiles.py b/senlinclient/tests/functional/test_profiles.py new file mode 100644 index 00000000..3054f64f --- /dev/null +++ b/senlinclient/tests/functional/test_profiles.py @@ -0,0 +1,23 @@ +# 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 senlinclient.tests.functional import base + + +class ProfileTest(base.OpenStackClientTestBase): + """Test for profiles""" + + def test_profile_list(self): + result = self.openstack('cluster profile list') + profile_list = self.parser.listing(result) + self.assertTableStruct(profile_list, ['id', 'name', 'type', + 'created_at']) diff --git a/senlinclient/tests/functional/test_readonly_senlin.py b/senlinclient/tests/functional/test_readonly_senlin.py new file mode 100644 index 00000000..88019f98 --- /dev/null +++ b/senlinclient/tests/functional/test_readonly_senlin.py @@ -0,0 +1,24 @@ +# 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 tempest.lib import exceptions + +from senlinclient.tests.functional import base + + +class FakeTest(base.OpenStackClientTestBase): + """Test if fake actions can be detected""" + + def test_fake_action(self): + self.assertRaises(exceptions.CommandFailed, + self.openstack, + 'this-does-not-exist') diff --git a/senlinclient/tests/functional/test_receivers.py b/senlinclient/tests/functional/test_receivers.py new file mode 100644 index 00000000..423d6630 --- /dev/null +++ b/senlinclient/tests/functional/test_receivers.py @@ -0,0 +1,24 @@ +# 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 senlinclient.tests.functional import base + + +class ReceiverTest(base.OpenStackClientTestBase): + """Test for receivers""" + + def test_receiver_list(self): + result = self.openstack('cluster receiver list') + receiver_list = self.parser.listing(result) + self.assertTableStruct(receiver_list, ['id', 'name', 'type', + 'cluster_id', 'action', + 'created_at']) diff --git a/senlinclient/tests/functional/test_version.py b/senlinclient/tests/functional/test_version.py new file mode 100644 index 00000000..fce0b1b0 --- /dev/null +++ b/senlinclient/tests/functional/test_version.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 senlinclient.tests.functional import base + + +class VersionTest(base.OpenStackClientTestBase): + """Test for versions""" + + def test_openstack_version(self): + self.openstack('', flags='--version') diff --git a/test-requirements.txt b/test-requirements.txt index 1b154290..175faf77 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -9,9 +9,11 @@ fixtures>=3.0.0 # Apache-2.0/BSD requests-mock>=1.1.0 # Apache-2.0 mock>=2.0.0 # BSD openstackdocstheme>=1.18.1 # Apache-2.0 +python-openstackclient>=3.12.0 # Apache-2.0 oslotest>=3.2.0 # Apache-2.0 setuptools!=24.0.0,!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,!=36.2.0,>=16.0 # PSF/ZPL sphinx!=1.6.6,>=1.6.2 # BSD +tempest>=17.1.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=2.2.0 # MIT diff --git a/tox.ini b/tox.ini index d32743cc..efcb672f 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,8 @@ minversion = 2.0 skipsdist = True [testenv] +setenv = VIRTUAL_ENV={envdir} + CLIENT_NAME=python-senlinclient usedevelop = True install_command = pip install {opts} {packages} deps = @@ -25,6 +27,12 @@ whitelist_externals = bash [testenv:venv] commands = {posargs} +[testenv:functional] +setenv = + {[testenv]setenv} + OS_TEST_PATH = ./senlinclient/tests/functional +passenv = OS_* + [testenv:cover] commands = python setup.py testr --coverage --testr-args='{posargs}'