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
This commit is contained in:
Adam Gandelman 2015-03-05 17:20:03 -08:00
parent fd6f36474b
commit d76862b186
23 changed files with 138 additions and 17 deletions

2
.gitignore vendored
View File

@ -31,4 +31,4 @@ cover
AUTHORS
ChangeLog
*.sqlite
test.conf

View File

@ -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

View File

@ -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)

View File

View File

@ -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):

View File

@ -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

View File

@ -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'

View File

@ -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',

View File

@ -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):

View File

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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

26
tools/run_functional.sh Executable file
View File

@ -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 <<END >$CONFIG_FILE
[functional]
api_version = 1
auth_strategy=noauth
os_auth_token=$OS_AUTH_TOKEN
ironic_url=$IRONIC_URL
END
else
cat <<END >$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

View File

@ -28,6 +28,9 @@ commands =
[testenv:venv]
commands = {posargs}
[testenv:functional]
setenv = OS_TEST_PATH=./ironicclient/tests/functional
[flake8]
ignore = E126,E127,E128
builtins = _