Refactor cue client tests

- Added fixtures to test controllers

Change-Id: Ieb8c5053583f2e6b797e1d530c369ea0c7dc6a2c
This commit is contained in:
Steve Leon 2015-04-23 12:44:27 -07:00
parent 9590b5ff8d
commit d5b3acd521
9 changed files with 294 additions and 419 deletions

View File

@ -14,13 +14,53 @@
import argparse
import mock
from oslo.serialization import jsonutils
from requests_mock.contrib import fixture as requests_mock_fixture
import six
import testtools
from cueclient.tests import utils
from cueclient.tests.fixture_data import V1
class TestCueBase(utils.TestCommand):
class TestCueBase(testtools.TestCase):
def setUp(self):
super(TestCueBase, self).setUp()
self.app = mock.Mock(name='app')
self.app.client_manager = mock.Mock(name='client_manager')
self.namespace = argparse.Namespace()
self.requests = self.useFixture(requests_mock_fixture.Fixture())
fix = V1(self.requests)
client_fixture = self.useFixture(fix)
cs = client_fixture.client
# Build up a fake app
self.app = mock.Mock()
self.app.client_manager = mock.Mock()
self.app.client_manager.mq = cs
def check_parser(self, cmd, args, verify_args):
"""Test for parsing arguments"""
cmd_parser = cmd.get_parser('check_parser')
parsed_args = cmd_parser.parse_args(args)
for av in verify_args:
attr, value = av
if attr:
self.assertIn(attr, parsed_args)
self.assertEqual(getattr(parsed_args, attr), value)
return parsed_args
def execute(self, cmd_class, arglist, verifylist):
cmd = cmd_class(self.app, argparse.Namespace())
parsed_args = self.check_parser(cmd, arglist, verifylist)
return cmd.take_action(parsed_args)
def assert_called(self, method, path, body=None):
self.assertEqual(self.requests.last_request.method, method)
self.assertEqual(self.requests.last_request.path_url, path)
if body:
req_data = self.requests.last_request.body
if isinstance(req_data, six.binary_type):
req_data = req_data.decode('utf-8')
if not isinstance(body, six.string_types):
# json load if the input body to match against is not a string
req_data = jsonutils.loads(req_data)
self.assertEqual(req_data, body)

View File

@ -1,81 +0,0 @@
# Copyright 2013 Nebula Inc.
#
# 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 sys
import six
AUTH_TOKEN = "foobar"
AUTH_URL = "http://0.0.0.0"
class FakeStdout:
def __init__(self):
self.content = []
def write(self, text):
self.content.append(text)
def make_string(self):
result = ''
for line in self.content:
result = result + line
return result
class FakeApp(object):
def __init__(self, _stdout):
self.stdout = _stdout
self.client_manager = None
self.stdin = sys.stdin
self.stdout = _stdout or sys.stdout
self.stderr = sys.stderr
self.restapi = None
class FakeClientManager(object):
def __init__(self):
self.compute = None
self.identity = None
self.image = None
self.object = None
self.volume = None
self.network = None
self.auth_ref = None
class FakeModule(object):
def __init__(self, name, version):
self.name = name
self.__version__ = version
class FakeResource(object):
def __init__(self, manager, info, loaded=False):
self.manager = manager
self._info = info
self._add_details(info)
self._loaded = loaded
def _add_details(self, info):
for (k, v) in six.iteritems(info):
setattr(self, k, v)
def __repr__(self):
reprkeys = sorted(k for k in self.__dict__.keys() if k[0] != '_' and
k != 'manager')
info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
return "<%s %s>" % (self.__class__.__name__, info)

View File

@ -0,0 +1,101 @@
# 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 fixtures
from keystoneclient import session
from six.moves.urllib import parse
from cueclient.v1 import client
MESSAGE_QUEUE_URL = 'http://message.queue'
class V1(fixtures.Fixture):
base_url = 'clusters'
json_headers = {'Content-Type': 'application/json'}
def __init__(self, requests):
super(V1, self).__init__()
self.client = None
self.requests = requests
def setUp(self):
super(V1, self).setUp()
self.cluster_1234 = {
"name": "test-cluster",
"id": "00000000-0000-0000-0000-000000001234",
"size": 1,
"network_id": ["05860da0-e2bd-4315-9cfb-7dd6e9963cd9"],
"created_at": "2015-01-01T00:00:00+00:00",
"end_points": [],
"flavor": "1",
"status": "ACTIVE",
}
self.cluster_5678 = {
"name": "test-cluster2",
"id": "00000000-0000-0000-0000-000000005678",
"size": 3,
"network_id": ["05567na0-f7aa-6820-7afcd-7dd6e9963cd9"],
"created_at": "2015-01-01T00:00:00+00:00",
"end_points": [],
"flavor": "1",
"status": "BUILDING",
}
self.new_cluster = {
"name": "new-test-cluster",
"id": "00000000-0000-0000-0000-000000009012",
"size": 3,
"network_id": ["05567na0-f7aa-6820-7afcd-7dd6e9963cd9"],
"created_at": "2015-01-01T00:00:00+00:00",
"end_points": [],
"flavor": "1",
"status": "BUILDING",
}
clusters = [self.cluster_1234, self.cluster_5678]
self.requests.register_uri('GET', self.url(),
json=clusters,
headers=self.json_headers)
for cluster in clusters:
self.requests.register_uri('GET', self.url(cluster['id']),
json=cluster,
headers=self.json_headers)
for cluster in clusters:
self.requests.register_uri('DELETE', self.url(cluster['id']),
status_code=202)
self.requests.register_uri('POST', self.url(),
json=self.new_cluster,
headers=self.json_headers)
self.client = client.Client(session=session.Session())
self.client.session.endpoint_override = MESSAGE_QUEUE_URL
def url(self, *args, **kwargs):
url_args = [MESSAGE_QUEUE_URL]
if self.base_url:
url_args.append(self.base_url)
url = '/'.join(str(a).strip('/') for a in tuple(url_args) + args)
if kwargs:
url += '?%s' % parse.urlencode(kwargs, doseq=True)
return url

View File

View File

@ -0,0 +1,147 @@
# 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 cueclient.tests import base
from cueclient.v1.cli import clusters
class TestListClusters(base.TestCueBase):
def test_list_clusters(self):
"""test cluster list."""
arglist = []
verifylist = []
expected = {'00000000-0000-0000-0000-000000001234':
('00000000-0000-0000-0000-000000001234',
'test-cluster', 'ACTIVE', []),
'00000000-0000-0000-0000-000000005678':
('00000000-0000-0000-0000-000000005678',
'test-cluster2', 'BUILDING', [])}
result = self.execute(clusters.ListClustersCommand, arglist,
verifylist)
self.assertEqual(['id', 'name', 'status', 'end_points'], result[0])
self.assert_called('GET', '/clusters')
for cluster in result[1]:
self.assertEqual(expected[cluster[0]], cluster)
class TestShowCluster(base.TestCueBase):
def test_show_cluster(self):
"""test cluster show."""
cluster_id = '00000000-0000-0000-0000-000000001234'
arglist = [cluster_id]
verifylist = []
result = self.execute(clusters.ShowClusterCommand, arglist, verifylist)
expected = [('created_at', 'end_points', 'flavor', 'id', 'name',
'network_id', 'size', 'status'),
(u'2015-01-01T00:00:00+00:00', [], '1',
'00000000-0000-0000-0000-000000001234',
'test-cluster', [u'05860da0-e2bd-4315-9cfb-7dd6e9963cd9'],
1, 'ACTIVE')]
self.assert_called('GET', '/clusters/' + cluster_id)
self.assertEqual(expected, result)
def test_show_cluster_without_id(self):
"""test show cluster without specifying cluster id"""
arglist = []
verifylist = []
self.assertRaises(SystemExit, self.execute,
clusters.ShowClusterCommand, arglist, verifylist)
class TestCreateCluster(base.TestCueBase):
cluster_name = "test_Cluster"
cluster_network_id = "9d6708ee-ea48-4e78-bef6-b50b48405091"
cluster_flavor = "1"
cluster_size = "2"
def test_create_cluster(self):
arglist = ["--name", self.cluster_name,
"--nic", self.cluster_network_id,
"--flavor", self.cluster_flavor,
"--size", self.cluster_size]
verifylist = [
('name', self.cluster_name),
('nic', self.cluster_network_id),
('flavor', self.cluster_flavor),
('size', self.cluster_size)
]
self.execute(clusters.CreateClusterCommand, arglist, verifylist)
self.assert_called('POST', '/clusters')
def test_create_cluster_without_name(self):
"""test create cluster without 'name' argument."""
arglist = ["--nic", self.cluster_network_id,
"--flavor", self.cluster_flavor,
"--size", self.cluster_size]
verifylist = []
self.assertRaises(SystemExit, self.execute,
clusters.CreateClusterCommand, arglist, verifylist)
def test_create_cluster_without_nic(self):
"""test create cluster without 'network_id' argument."""
arglist = ["--name", self.cluster_name,
"--flavor", self.cluster_flavor,
"--size", self.cluster_size]
verifylist = []
self.assertRaises(SystemExit, self.execute,
clusters.CreateClusterCommand, arglist, verifylist)
def test_create_cluster_without_flavor(self):
"""test create cluster without 'flavor' argument."""
arglist = ["--name", self.cluster_name,
"--nic", self.cluster_network_id,
"--size", self.cluster_size]
verifylist = []
self.assertRaises(SystemExit, self.execute,
clusters.CreateClusterCommand, arglist, verifylist)
def test_create_cluster_without_size(self):
"""test create cluster without 'size' argument."""
arglist = ["--name", self.cluster_name,
"--nic", self.cluster_network_id,
"--flavor", self.cluster_flavor]
verifylist = []
self.assertRaises(SystemExit, self.execute,
clusters.CreateClusterCommand, arglist, verifylist)
class TestDeleteCluster(base.TestCueBase):
def test_delete_cluster_without_id(self):
"""test delete cluster without giving cluster id"""
arglist = []
verifylist = []
self.assertRaises(SystemExit, self.execute,
clusters.DeleteClusterCommand, arglist, verifylist)
def test_delete_cluster(self):
"""test delete cluster"""
cluster_id = '00000000-0000-0000-0000-000000001234'
arglist = [cluster_id]
verifylist = []
result = self.execute(clusters.DeleteClusterCommand, arglist,
verifylist)
self.assert_called('DELETE', '/clusters/' + cluster_id)
self.assertEqual(None, result)

View File

@ -1,92 +0,0 @@
# Copyright 2012-2013 OpenStack Foundation
# Copyright 2013 Nebula Inc.
#
# 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
import sys
import fixtures
import testtools
from cueclient.tests import fakes
class TestCase(testtools.TestCase):
def setUp(self):
testtools.TestCase.setUp(self)
if (os.environ.get("OS_STDOUT_CAPTURE") == "True" or
os.environ.get("OS_STDOUT_CAPTURE") == "1"):
stdout = self.useFixture(fixtures.StringStream("stdout")).stream
self.useFixture(fixtures.MonkeyPatch("sys.stdout", stdout))
if (os.environ.get("OS_STDERR_CAPTURE") == "True" or
os.environ.get("OS_STDERR_CAPTURE") == "1"):
stderr = self.useFixture(fixtures.StringStream("stderr")).stream
self.useFixture(fixtures.MonkeyPatch("sys.stderr", stderr))
def assertNotCalled(self, m, msg=None):
"""Assert a function was not called."""
if m.called:
if not msg:
msg = 'method %s should not have been called' % m
self.fail(msg)
# 2.6 doesn't have the assert dict equals so make sure that it exists
if tuple(sys.version_info)[0:2] < (2, 7):
def assertIsInstance(self, obj, cls, msg=None):
"""self.assertTrue(isinstance(obj, cls)), with a nicer message."""
if not isinstance(obj, cls):
standardMsg = '%s is not an instance of %r' % (obj, cls)
self.fail(self._formatMessage(msg, standardMsg))
def assertDictEqual(self, d1, d2, msg=None):
# Simple version taken from 2.7
self.assertIsInstance(d1, dict,
'First argument is not a dictionary')
self.assertIsInstance(d2, dict,
'Second argument is not a dictionary')
if d1 != d2:
if msg:
self.fail(msg)
else:
standardMsg = '%r != %r' % (d1, d2)
self.fail(standardMsg)
class TestCommand(TestCase):
"""Test cliff command classes."""
def setUp(self):
super(TestCommand, self).setUp()
# Build up a fake app
self.fake_stdout = fakes.FakeStdout()
self.app = fakes.FakeApp(self.fake_stdout)
self.app.client_manager = fakes.FakeClientManager()
def check_parser(self, cmd, args, verify_args):
"""Test for parsing arguments"""
cmd_parser = cmd.get_parser('check_parser')
parsed_args = cmd_parser.parse_args(args)
for av in verify_args:
attr, value = av
if attr:
self.assertIn(attr, parsed_args)
self.assertEqual(getattr(parsed_args, attr), value)
return parsed_args

View File

@ -1,241 +0,0 @@
# 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 mock
from cueclient.tests import base
from cueclient.v1.cli import clusters
class TestListClusters(base.TestCueBase):
def test_list_clusters(self):
"""test cluster list."""
arglist = [
]
verifylist = [
]
response = {"id": "111",
"name": "cluster_01",
"status": "BUILDING"}
lister = mock.Mock(return_value=response)
self.app.client_manager.mq.clusters.list = lister
cmd = clusters.ListClustersCommand(self.app, self.namespace)
parsed_args = self.check_parser(cmd, arglist, verifylist)
result = cmd.take_action(parsed_args)
self.assertEqual(['id', 'name', 'status', 'end_points'], result[0])
class TestCreateCluster(base.TestCueBase):
cluster_name = "test_Cluster"
cluster_network_id = "9d6708ee-ea48-4e78-bef6-b50b48405091"
cluster_flavor = "1"
cluster_size = "2"
def test_create_cluster(self):
"""test to create a new cluster with all required input arguments"""
arglist = ["--name", self.cluster_name,
"--nic", self.cluster_network_id,
"--flavor", self.cluster_flavor,
"--size", self.cluster_size]
verifylist = [
('name', self.cluster_name),
('nic', self.cluster_network_id),
('flavor', self.cluster_flavor),
('size', self.cluster_size)
]
response = {"id": "222",
"project_id": "test",
"network_id": [self.cluster_network_id],
"name": self.cluster_name,
"status": "BUILDING",
"flavor": self.cluster_flavor,
"size": self.cluster_size,
"volume_size": "1024",
"deleted": "0",
"created_at": "2015-02-04 00:35:02",
"updated_at": "2015-02-04 00:35:02",
"deleted_at": ""}
mocker = mock.Mock(return_value=response)
self.app.client_manager.mq.clusters.create = mocker
cmd = clusters.CreateClusterCommand(self.app, self.namespace)
parsed_args = self.check_parser(cmd, arglist, verifylist)
result = list(cmd.take_action(parsed_args))
filtered = [('created_at', 'deleted', 'deleted_at', 'flavor', 'id',
'name', 'network_id', 'project_id', 'size', 'status',
'updated_at', 'volume_size'),
('2015-02-04 00:35:02', '0', '', '1',
'222', 'test_Cluster',
['9d6708ee-ea48-4e78-bef6-b50b48405091'], 'test', '2',
'BUILDING', '2015-02-04 00:35:02', '1024')]
self.assertEqual(filtered, result)
def test_create_cluster_without_name(self):
"""test create cluster without 'name' argument."""
arglist = ["--nic", self.cluster_network_id,
"--flavor", self.cluster_flavor,
"--size", self.cluster_size]
verifylist = [
]
mocker = mock.Mock(return_value=None)
self.app.client_manager.mq.clusters.create = mocker
cmd = clusters.CreateClusterCommand(self.app, self.namespace)
self.assertRaises(SystemExit, self.check_parser,
cmd, arglist, verifylist)
def test_create_cluster_without_nic(self):
"""test create cluster without 'network_id' argument."""
arglist = ["--name", self.cluster_name,
"--flavor", self.cluster_flavor,
"--size", self.cluster_size]
verifylist = [
]
mocker = mock.Mock(return_value=None)
self.app.client_manager.mq.clusters.create = mocker
cmd = clusters.CreateClusterCommand(self.app, self.namespace)
self.assertRaises(SystemExit, self.check_parser,
cmd, arglist, verifylist)
def test_create_cluster_without_flavor(self):
"""test create cluster without 'flavor' argument."""
arglist = ["--name", self.cluster_name,
"--nic", self.cluster_network_id,
"--size", self.cluster_size]
verifylist = [
]
mocker = mock.Mock(return_value=None)
self.app.client_manager.mq.clusters.create = mocker
cmd = clusters.CreateClusterCommand(self.app, self.namespace)
self.assertRaises(SystemExit, self.check_parser,
cmd, arglist, verifylist)
def test_create_cluster_without_size(self):
"""test create cluster without 'size' argument."""
response = {
}
arglist = ["--name", self.cluster_name,
"--flavor", self.cluster_flavor,
"--size", self.cluster_size]
verifylist = [
]
mocker = mock.Mock(return_value=response)
self.app.client_manager.mq.clusters.create = mocker
cmd = clusters.CreateClusterCommand(self.app, self.namespace)
self.assertRaises(SystemExit, self.check_parser,
cmd, arglist, verifylist)
class TestShowCluster(base.TestCueBase):
def test_show_cluster(self):
"""test show cluster with correct cluster id"""
cluster_id = 'e531f2b3-3d97-42c0-b3b5-b7b6ab532018'
response = {
"id": cluster_id,
"project_id": "test",
"network_id": ["9d6708ee-ea48-4e78-bef6-b50b48405091"],
"name": "test_cluster",
"status": "BUILDING",
"flavor": "1",
"size": "2",
"volume_size": "1024"
}
arglist = [cluster_id]
verifylist = [
]
mocker = mock.Mock(return_value=response)
self.app.client_manager.mq.clusters.get = mocker
cmd = clusters.ShowClusterCommand(self.app, self.namespace)
parsed_args = self.check_parser(cmd, arglist, verifylist)
result = list(cmd.take_action(parsed_args))
filtered = [('flavor', 'id', 'name', 'network_id', 'project_id',
'size', 'status', 'volume_size'),
('1', 'e531f2b3-3d97-42c0-b3b5-b7b6ab532018',
'test_cluster', ['9d6708ee-ea48-4e78-bef6-b50b48405091'],
'test', '2', 'BUILDING', '1024')]
self.assertEqual(filtered, result)
def test_show_cluster_without_id(self):
"""test show cluster without specifying cluster id"""
arglist = [
]
verifylist = [
]
mocker = mock.Mock(return_value=None)
self.app.client_manager.mq.clusters.get = mocker
cmd = clusters.ShowClusterCommand(self.app, self.namespace)
self.assertRaises(SystemExit, self.check_parser,
cmd, arglist, verifylist)
class TestDeleteCluster(base.TestCueBase):
"""test delete cluster with correct cluster id"""
def test_delete_cluster(self):
cluster_id = 'e531f2b3-3d97-42c0-b3b5-b7b6ab532018'
arglist = [
cluster_id
]
verifylist = [
]
mocker = mock.Mock(return_value=None)
self.app.client_manager.mq.clusters.delete = mocker
cmd = clusters.DeleteClusterCommand(self.app, self.namespace)
parsed_args = self.check_parser(cmd, arglist, verifylist)
result = cmd.take_action(parsed_args)
mocker.assert_called_with(cluster_id)
self.assertEqual(None, result)
def test_delete_cluster_without_id(self):
"""test show cluster without giving cluster id"""
arglist = [
]
verifylist = [
]
mocker = mock.Mock(return_value=None)
self.app.client_manager.mq.clusters.get = mocker
cmd = clusters.DeleteClusterCommand(self.app, self.namespace)
self.assertRaises(SystemExit, self.check_parser,
cmd, arglist, verifylist)

View File

@ -7,6 +7,7 @@ coverage>=3.6
discover
fixtures>=0.3.14
mock>=1.0
requests-mock>=0.6.0
python-subunit>=0.0.18
testrepository>=0.0.18