From d76862b1869ea529da1e149f4e3a00cc5fb9eda6 Mon Sep 17 00:00:00 2001 From: Adam Gandelman Date: Thu, 5 Mar 2015 17:20:03 -0800 Subject: [PATCH] Adds basic ironicclient functional testing This moves unit tests to ironicclient/tests/unit and adds a new test directory at ironicclient/tests/functional. These are meant to be functional tests that are run against a living cloud (presumably deployed by devstack as part of a gating job). They depend on a test.conf to exist that contains admin user credentials for said cloud. This includes a simple run_functional.sh script that is meant to create that and serve as the entry point for running the tests from a devstack post_test_hook. Change-Id: I11570c3e22e4f80b94d0643dca6ed8231217c877 --- .gitignore | 2 +- .testr.conf | 4 +- .../tests/{v1 => functional}/__init__.py | 0 .../tests/functional/test_ironicclient.py | 92 +++++++++++++++++++ ironicclient/tests/unit/__init__.py | 0 .../{ => unit}/keystone_client_fixtures.py | 0 ironicclient/tests/{ => unit}/test_client.py | 2 +- ironicclient/tests/{ => unit}/test_http.py | 2 +- ironicclient/tests/{ => unit}/test_import.py | 2 +- ironicclient/tests/{ => unit}/test_shell.py | 4 +- ironicclient/tests/{ => unit}/test_utils.py | 2 +- ironicclient/tests/{ => unit}/utils.py | 0 ironicclient/tests/unit/v1/__init__.py | 0 .../tests/{ => unit}/v1/test_chassis.py | 2 +- .../tests/{ => unit}/v1/test_chassis_shell.py | 2 +- .../tests/{ => unit}/v1/test_driver.py | 2 +- .../tests/{ => unit}/v1/test_driver_shell.py | 2 +- ironicclient/tests/{ => unit}/v1/test_node.py | 2 +- .../tests/{ => unit}/v1/test_node_shell.py | 2 +- ironicclient/tests/{ => unit}/v1/test_port.py | 2 +- .../tests/{ => unit}/v1/test_port_shell.py | 2 +- tools/run_functional.sh | 26 ++++++ tox.ini | 3 + 23 files changed, 138 insertions(+), 17 deletions(-) rename ironicclient/tests/{v1 => functional}/__init__.py (100%) create mode 100644 ironicclient/tests/functional/test_ironicclient.py create mode 100644 ironicclient/tests/unit/__init__.py rename ironicclient/tests/{ => unit}/keystone_client_fixtures.py (100%) rename ironicclient/tests/{ => unit}/test_client.py (99%) rename ironicclient/tests/{ => unit}/test_http.py (99%) rename ironicclient/tests/{ => unit}/test_import.py (97%) rename ironicclient/tests/{ => unit}/test_shell.py (99%) rename ironicclient/tests/{ => unit}/test_utils.py (99%) rename ironicclient/tests/{ => unit}/utils.py (100%) create mode 100644 ironicclient/tests/unit/v1/__init__.py rename ironicclient/tests/{ => unit}/v1/test_chassis.py (99%) rename ironicclient/tests/{ => unit}/v1/test_chassis_shell.py (96%) rename ironicclient/tests/{ => unit}/v1/test_driver.py (99%) rename ironicclient/tests/{ => unit}/v1/test_driver_shell.py (98%) rename ironicclient/tests/{ => unit}/v1/test_node.py (99%) rename ironicclient/tests/{ => unit}/v1/test_node_shell.py (99%) rename ironicclient/tests/{ => unit}/v1/test_port.py (99%) rename ironicclient/tests/{ => unit}/v1/test_port_shell.py (98%) create mode 100755 tools/run_functional.sh diff --git a/.gitignore b/.gitignore index a7b52ecdf..7ebbf21bc 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,4 @@ cover AUTHORS ChangeLog *.sqlite - +test.conf diff --git a/.testr.conf b/.testr.conf index d9963385f..80269e12b 100644 --- a/.testr.conf +++ b/.testr.conf @@ -1,5 +1,5 @@ [DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} ${PYTHON:-python} -m subunit.run discover -t ./ ./ $LISTOPT $IDOPTION +test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./ironicclient/tests/unit} $LISTOPT $IDOPTION + test_id_option=--load-list $IDFILE test_list_option=--list - diff --git a/ironicclient/tests/v1/__init__.py b/ironicclient/tests/functional/__init__.py similarity index 100% rename from ironicclient/tests/v1/__init__.py rename to ironicclient/tests/functional/__init__.py diff --git a/ironicclient/tests/functional/test_ironicclient.py b/ironicclient/tests/functional/test_ironicclient.py new file mode 100644 index 000000000..a8117bc43 --- /dev/null +++ b/ironicclient/tests/functional/test_ironicclient.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# 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. + +import ConfigParser +import os + +import testtools + +import ironicclient +from ironicclient import exc + +DEFAULT_CONFIG = os.path.join(os.path.dirname(__file__), 'test.conf') + + +class TestIronicClient(testtools.TestCase): + def setUp(self): + super(TestIronicClient, self).setUp() + self.client = ironicclient.client.get_client(**self._get_config()) + + def _get_config(self): + config_file = os.environ.get('IRONICCLIENT_TEST_CONFIG', + DEFAULT_CONFIG) + config = ConfigParser.SafeConfigParser() + if not config.read(config_file): + self.skipTest('Skipping, no test config found @ %s' % config_file) + try: + auth_strategy = config.get('functional', 'auth_strategy') + except ConfigParser.NoOptionError: + auth_strategy = 'keystone' + if auth_strategy not in ['keystone', 'noauth']: + raise self.fail( + 'Invalid auth type specified in functional must be one of: ' + 'keystone, noauth') + out = {} + conf_settings = ['api_version'] + if auth_strategy == 'keystone': + conf_settings += ['os_auth_url', 'os_username', + 'os_password', 'os_tenant_name'] + + else: + conf_settings += ['os_auth_token', 'ironic_url'] + + for c in conf_settings: + try: + out[c] = config.get('functional', c) + except ConfigParser.NoOptionError: + out[c] = None + missing = [k for k, v in out.items() if not v] + if missing: + self.fail('Missing required setting in test.conf (%s) for ' + 'auth_strategy=%s: %s' % + (config_file, auth_strategy, ','.join(missing))) + return out + + def _try_delete_resource(self, resource, id): + mgr = getattr(self.client, resource) + try: + mgr.delete(id) + except exc.NotFound: + pass + + def _create_node(self, **kwargs): + if 'driver' not in kwargs: + kwargs['driver'] = 'fake' + node = self.client.node.create(**kwargs) + self.addCleanup(self._try_delete_resource, 'node', node.uuid) + return node + + def test_node_list(self): + self.assertTrue(isinstance(self.client.node.list(), list)) + + def test_node_create_get_delete(self): + node = self._create_node() + self.assertTrue(isinstance(node, ironicclient.v1.node.Node)) + got = self.client.node.get(node.uuid) + self.assertTrue(isinstance(got, ironicclient.v1.node.Node)) + self.client.node.delete(node.uuid) + self.assertRaises(exc.NotFound, self.client.node.get, node.uuid) diff --git a/ironicclient/tests/unit/__init__.py b/ironicclient/tests/unit/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ironicclient/tests/keystone_client_fixtures.py b/ironicclient/tests/unit/keystone_client_fixtures.py similarity index 100% rename from ironicclient/tests/keystone_client_fixtures.py rename to ironicclient/tests/unit/keystone_client_fixtures.py diff --git a/ironicclient/tests/test_client.py b/ironicclient/tests/unit/test_client.py similarity index 99% rename from ironicclient/tests/test_client.py rename to ironicclient/tests/unit/test_client.py index b2b21c3d0..1c2f356fe 100644 --- a/ironicclient/tests/test_client.py +++ b/ironicclient/tests/unit/test_client.py @@ -16,7 +16,7 @@ import fixtures from ironicclient.client import get_client from ironicclient import exc -from ironicclient.tests import utils +from ironicclient.tests.unit import utils def fake_get_ksclient(**kwargs): diff --git a/ironicclient/tests/test_http.py b/ironicclient/tests/unit/test_http.py similarity index 99% rename from ironicclient/tests/test_http.py rename to ironicclient/tests/unit/test_http.py index 063537148..72910835c 100644 --- a/ironicclient/tests/test_http.py +++ b/ironicclient/tests/unit/test_http.py @@ -21,7 +21,7 @@ import six from ironicclient.common import http from ironicclient import exc -from ironicclient.tests import utils +from ironicclient.tests.unit import utils HTTP_CLASS = six.moves.http_client.HTTPConnection diff --git a/ironicclient/tests/test_import.py b/ironicclient/tests/unit/test_import.py similarity index 97% rename from ironicclient/tests/test_import.py rename to ironicclient/tests/unit/test_import.py index 14e9b249d..09d3c725c 100644 --- a/ironicclient/tests/test_import.py +++ b/ironicclient/tests/unit/test_import.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -from ironicclient.tests import utils +from ironicclient.tests.unit import utils module_str = 'ironicclient' diff --git a/ironicclient/tests/test_shell.py b/ironicclient/tests/unit/test_shell.py similarity index 99% rename from ironicclient/tests/test_shell.py rename to ironicclient/tests/unit/test_shell.py index 48c6693ab..684bf7e19 100644 --- a/ironicclient/tests/test_shell.py +++ b/ironicclient/tests/unit/test_shell.py @@ -30,8 +30,8 @@ from testtools import matchers from ironicclient import exc from ironicclient import shell as ironic_shell -from ironicclient.tests import keystone_client_fixtures -from ironicclient.tests import utils +from ironicclient.tests.unit import keystone_client_fixtures +from ironicclient.tests.unit import utils FAKE_ENV = {'OS_USERNAME': 'username', 'OS_PASSWORD': 'password', diff --git a/ironicclient/tests/test_utils.py b/ironicclient/tests/unit/test_utils.py similarity index 99% rename from ironicclient/tests/test_utils.py rename to ironicclient/tests/unit/test_utils.py index 595e5a3d8..e529dbf01 100644 --- a/ironicclient/tests/test_utils.py +++ b/ironicclient/tests/unit/test_utils.py @@ -19,7 +19,7 @@ import mock from ironicclient.common import utils from ironicclient import exc -from ironicclient.tests import utils as test_utils +from ironicclient.tests.unit import utils as test_utils class UtilsTest(test_utils.BaseTestCase): diff --git a/ironicclient/tests/utils.py b/ironicclient/tests/unit/utils.py similarity index 100% rename from ironicclient/tests/utils.py rename to ironicclient/tests/unit/utils.py diff --git a/ironicclient/tests/unit/v1/__init__.py b/ironicclient/tests/unit/v1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ironicclient/tests/v1/test_chassis.py b/ironicclient/tests/unit/v1/test_chassis.py similarity index 99% rename from ironicclient/tests/v1/test_chassis.py rename to ironicclient/tests/unit/v1/test_chassis.py index 7ca3b96ac..5252e8ed8 100644 --- a/ironicclient/tests/v1/test_chassis.py +++ b/ironicclient/tests/unit/v1/test_chassis.py @@ -20,7 +20,7 @@ import copy import testtools from testtools.matchers import HasLength -from ironicclient.tests import utils +from ironicclient.tests.unit import utils import ironicclient.v1.chassis CHASSIS = {'id': 42, diff --git a/ironicclient/tests/v1/test_chassis_shell.py b/ironicclient/tests/unit/v1/test_chassis_shell.py similarity index 96% rename from ironicclient/tests/v1/test_chassis_shell.py rename to ironicclient/tests/unit/v1/test_chassis_shell.py index ef54f98d0..21d036647 100644 --- a/ironicclient/tests/v1/test_chassis_shell.py +++ b/ironicclient/tests/unit/v1/test_chassis_shell.py @@ -17,7 +17,7 @@ import mock from ironicclient.openstack.common import cliutils -from ironicclient.tests import utils +from ironicclient.tests.unit import utils import ironicclient.v1.chassis_shell as c_shell diff --git a/ironicclient/tests/v1/test_driver.py b/ironicclient/tests/unit/v1/test_driver.py similarity index 99% rename from ironicclient/tests/v1/test_driver.py rename to ironicclient/tests/unit/v1/test_driver.py index 5b446b865..aa4287b52 100644 --- a/ironicclient/tests/v1/test_driver.py +++ b/ironicclient/tests/unit/v1/test_driver.py @@ -20,7 +20,7 @@ import testtools from testtools import matchers from ironicclient import exc -from ironicclient.tests import utils +from ironicclient.tests.unit import utils from ironicclient.v1 import driver diff --git a/ironicclient/tests/v1/test_driver_shell.py b/ironicclient/tests/unit/v1/test_driver_shell.py similarity index 98% rename from ironicclient/tests/v1/test_driver_shell.py rename to ironicclient/tests/unit/v1/test_driver_shell.py index f7c38d880..5719c141c 100644 --- a/ironicclient/tests/v1/test_driver_shell.py +++ b/ironicclient/tests/unit/v1/test_driver_shell.py @@ -17,7 +17,7 @@ import mock from ironicclient.openstack.common import cliutils -from ironicclient.tests import utils +from ironicclient.tests.unit import utils import ironicclient.v1.driver_shell as d_shell diff --git a/ironicclient/tests/v1/test_node.py b/ironicclient/tests/unit/v1/test_node.py similarity index 99% rename from ironicclient/tests/v1/test_node.py rename to ironicclient/tests/unit/v1/test_node.py index 91663727f..32e6bea23 100644 --- a/ironicclient/tests/v1/test_node.py +++ b/ironicclient/tests/unit/v1/test_node.py @@ -22,7 +22,7 @@ import testtools from testtools.matchers import HasLength from ironicclient import exc -from ironicclient.tests import utils +from ironicclient.tests.unit import utils from ironicclient.v1 import node NODE1 = {'id': 123, diff --git a/ironicclient/tests/v1/test_node_shell.py b/ironicclient/tests/unit/v1/test_node_shell.py similarity index 99% rename from ironicclient/tests/v1/test_node_shell.py rename to ironicclient/tests/unit/v1/test_node_shell.py index cf267c1ad..ac03486fa 100644 --- a/ironicclient/tests/v1/test_node_shell.py +++ b/ironicclient/tests/unit/v1/test_node_shell.py @@ -19,7 +19,7 @@ import mock from ironicclient.common import utils as commonutils from ironicclient.openstack.common.apiclient import exceptions from ironicclient.openstack.common import cliutils -from ironicclient.tests import utils +from ironicclient.tests.unit import utils import ironicclient.v1.node_shell as n_shell diff --git a/ironicclient/tests/v1/test_port.py b/ironicclient/tests/unit/v1/test_port.py similarity index 99% rename from ironicclient/tests/v1/test_port.py rename to ironicclient/tests/unit/v1/test_port.py index 05717927c..b2d177e8d 100644 --- a/ironicclient/tests/v1/test_port.py +++ b/ironicclient/tests/unit/v1/test_port.py @@ -20,7 +20,7 @@ import copy import testtools from testtools.matchers import HasLength -from ironicclient.tests import utils +from ironicclient.tests.unit import utils import ironicclient.v1.port PORT = {'id': 987, diff --git a/ironicclient/tests/v1/test_port_shell.py b/ironicclient/tests/unit/v1/test_port_shell.py similarity index 98% rename from ironicclient/tests/v1/test_port_shell.py rename to ironicclient/tests/unit/v1/test_port_shell.py index fcc02358e..716f37d11 100644 --- a/ironicclient/tests/v1/test_port_shell.py +++ b/ironicclient/tests/unit/v1/test_port_shell.py @@ -18,7 +18,7 @@ import mock from ironicclient.common import utils as commonutils from ironicclient.openstack.common import cliutils -from ironicclient.tests import utils +from ironicclient.tests.unit import utils import ironicclient.v1.port_shell as p_shell diff --git a/tools/run_functional.sh b/tools/run_functional.sh new file mode 100755 index 000000000..4ac6c916b --- /dev/null +++ b/tools/run_functional.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +FUNC_TEST_DIR=$(dirname $0)/../ironicclient/tests/functional/ +CONFIG_FILE=$FUNC_TEST_DIR/test.conf + +if [[ -n "$OS_AUTH_TOKEN" ]] && [[ -n "$IRONIC_URL" ]]; then +cat <$CONFIG_FILE +[functional] +api_version = 1 +auth_strategy=noauth +os_auth_token=$OS_AUTH_TOKEN +ironic_url=$IRONIC_URL +END +else +cat <$CONFIG_FILE +[functional] +api_version = 1 +os_auth_url=$OS_AUTH_URL +os_username=$OS_USERNAME +os_password=$OS_PASSWORD +os_tenant_name=$OS_TENANT_NAME +os_service_type=baremetal +os_endpoint_type=public +END +fi +tox -e functional diff --git a/tox.ini b/tox.ini index 6b272088d..06cb1f846 100644 --- a/tox.ini +++ b/tox.ini @@ -28,6 +28,9 @@ commands = [testenv:venv] commands = {posargs} +[testenv:functional] +setenv = OS_TEST_PATH=./ironicclient/tests/functional + [flake8] ignore = E126,E127,E128 builtins = _