Run library unit tests against realistic data

This patch removes exit() calls from the HTTP Client
in order to uncover data processing errors. It configures
mocks to supply realistic data for specific requests and
to fail, on any unexpected ones.

Closes-bug: #1454343
Closes-bug: #1475642
Change-Id: I462702faa5c09fa743de1cbcd56b87757e1095a3
This commit is contained in:
Roman Prykhodchenko
2015-07-16 10:57:56 +02:00
parent f33de64253
commit f85a6eecbb
8 changed files with 118 additions and 82 deletions

View File

@@ -19,7 +19,6 @@ import requests
from keystoneclient.v2_0 import client as auth_client from keystoneclient.v2_0 import client as auth_client
from six.moves.urllib import parse as urlparse from six.moves.urllib import parse as urlparse
from fuelclient.cli.error import exceptions_decorator
from fuelclient import fuelclient_settings from fuelclient import fuelclient_settings
from fuelclient.logs import NullHandler from fuelclient.logs import NullHandler
@@ -59,7 +58,6 @@ class Client(object):
return '' return ''
@property @property
@exceptions_decorator
def auth_required(self): def auth_required(self):
if self._auth_required is None: if self._auth_required is None:
url = self.api_root + 'version' url = self.api_root + 'version'
@@ -98,7 +96,6 @@ class Client(object):
if self.debug: if self.debug:
print(message) print(message)
@exceptions_decorator
def delete_request(self, api): def delete_request(self, api):
"""Make DELETE request to specific API with some data """Make DELETE request to specific API with some data
""" """
@@ -114,7 +111,6 @@ class Client(object):
return resp.json() return resp.json()
@exceptions_decorator
def put_request(self, api, data): def put_request(self, api, data):
"""Make PUT request to specific API with some data """Make PUT request to specific API with some data
""" """
@@ -149,7 +145,6 @@ class Client(object):
params = params or {} params = params or {}
return requests.get(url, params=params, headers=headers) return requests.get(url, params=params, headers=headers)
@exceptions_decorator
def get_request(self, api, ostf=False, params=None): def get_request(self, api, ostf=False, params=None):
"""Make GET request to specific API """Make GET request to specific API
""" """
@@ -180,7 +175,6 @@ class Client(object):
return requests.post(url, data=data_json, headers=headers) return requests.post(url, data=data_json, headers=headers)
@exceptions_decorator
def post_request(self, api, data=None, ostf=False): def post_request(self, api, data=None, ostf=False):
"""Make POST request to specific API with some data """Make POST request to specific API with some data
""" """
@@ -189,7 +183,6 @@ class Client(object):
return resp.json() return resp.json()
@exceptions_decorator
def get_fuel_version(self): def get_fuel_version(self):
return self.get_request("version") return self.get_request("version")

View File

@@ -20,11 +20,13 @@ from fuelclient.tests.utils.fake_net_conf import get_fake_network_config
from fuelclient.tests.utils.fake_node import get_fake_node from fuelclient.tests.utils.fake_node import get_fake_node
from fuelclient.tests.utils.fake_env import get_fake_env from fuelclient.tests.utils.fake_env import get_fake_env
from fuelclient.tests.utils.fake_fuel_version import get_fake_fuel_version from fuelclient.tests.utils.fake_fuel_version import get_fake_fuel_version
from fuelclient.tests.utils.fake_task import get_fake_task
__all__ = (get_fake_env, __all__ = (get_fake_env,
get_fake_node, get_fake_fuel_version,
random_string,
get_fake_interface_config, get_fake_interface_config,
get_fake_node,
get_fake_network_config, get_fake_network_config,
get_fake_fuel_version) get_fake_task,
random_string)

View File

@@ -28,7 +28,8 @@ def get_fake_env(name=None, status=None, release_id=None,
'release_id': release_id or 1, 'release_id': release_id or 1,
'name': name or 'fake_env', 'name': name or 'fake_env',
'grouping': 'roles', 'grouping': 'roles',
'net_provider': 'nova_network', 'net_provider': 'neutron',
'net_segment_type': 'gre',
'fuel_version': fuel_version or '5.1', 'fuel_version': fuel_version or '5.1',
'pending_release_id': pending_release, 'pending_release_id': pending_release,
'id': env_id or 1, 'id': env_id or 1,

View File

@@ -28,18 +28,26 @@ class BaseLibTest(base.UnitTestCase):
self.m_request = rm.Mocker() self.m_request = rm.Mocker()
self.m_request.start() self.m_request.start()
self.session_adapter = self.m_request._adapter.register_uri(rm.ANY, self.top_matcher = self.m_request.register_uri(rm.ANY,
rm.ANY) rm.ANY,
json={})
self.api_client_patcher = patch.object(client.Client, self.auth_required_patch = patch.object(client.Client,
'auth_required', 'auth_required',
new_callable=mock.PropertyMock) new_callable=mock.PropertyMock)
self.m_api_client = self.api_client_patcher.start() self.m_auth_required = self.auth_required_patch.start()
self.m_api_client.return_value = False self.m_auth_required.return_value = False
self.addCleanup(self.m_request.stop)
self.addCleanup(self.auth_required_patch.stop)
def tearDown(self): def tearDown(self):
self.m_request.stop() calls = ['{method} {path}'.format(method=req.method, path=req.path)
self.api_client_patcher.stop() for req in self.top_matcher.request_history]
calls = '\n'.join(calls)
msg = 'Unexpected HTTP requests were detected:\n {0}'.format(calls)
self.assertFalse(self.top_matcher.called, msg=msg)
def get_object_uri(self, collection_path, object_id, attribute='/'): def get_object_uri(self, collection_path, object_id, attribute='/'):
return urlparse.urljoin(collection_path, str(object_id) + attribute) return urlparse.urljoin(collection_path, str(object_id) + attribute)

View File

@@ -15,13 +15,13 @@
# under the License. # under the License.
import mock import mock
import requests_mock as rm
import fuelclient import fuelclient
from fuelclient.cli import error from fuelclient.cli import error
from fuelclient.objects import base as base_object from fuelclient.objects import base as base_object
from fuelclient.objects import environment as env_object from fuelclient.objects import environment as env_object
from fuelclient.objects import task as task_object from fuelclient.objects import task as task_object
from fuelclient.tests import utils
from fuelclient.tests.v2.unit.lib import test_api from fuelclient.tests.v2.unit.lib import test_api
@@ -33,51 +33,59 @@ class TestEnvFacade(test_api.BaseLibTest):
self.version = 'v1' self.version = 'v1'
self.res_uri = '/api/{version}/clusters/'.format(version=self.version) self.res_uri = '/api/{version}/clusters/'.format(version=self.version)
self.fake_env = utils.get_fake_env()
self.fake_envs = [utils.get_fake_env() for i in range(10)]
self.client = fuelclient.get_client('environment', self.version) self.client = fuelclient.get_client('environment', self.version)
def test_env_list(self): def test_env_list(self):
matcher = self.m_request.get(self.res_uri, json=self.fake_envs)
self.client.get_all() self.client.get_all()
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(self.res_uri, self.session_adapter.last_request.path)
def test_env_show(self): def test_env_show(self):
env_id = 42 env_id = 42
expected_uri = self.get_object_uri(self.res_uri, env_id) expected_uri = self.get_object_uri(self.res_uri, env_id)
matcher = self.m_request.get(expected_uri, json=self.fake_env)
self.client.get_by_id(env_id) self.client.get_by_id(env_id)
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
def test_env_delete(self): def test_env_delete(self):
env_id = 42 env_id = 42
expected_uri = self.get_object_uri(self.res_uri, env_id) expected_uri = self.get_object_uri(self.res_uri, env_id)
matcher = self.m_request.delete(expected_uri, json={})
self.client.delete_by_id(env_id) self.client.delete_by_id(env_id)
self.assertEqual(rm.DELETE, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
@mock.patch.object(env_object.Environment, 'init_with_data') @mock.patch.object(env_object.Environment, 'init_with_data')
def test_env_create(self, m_init): def test_env_create(self, m_init):
node_name = 'test_node' env_name = self.fake_env['name']
release_id = 20 release_id = self.fake_env['release_id']
nst = 'gre' nst = self.fake_env['net_segment_type']
net = 'neutron' net = self.fake_env['net_provider']
mode = 'ha_compact'
self.client.create(node_name, release_id, net, mode, nst) matcher = self.m_request.post(self.res_uri, json=self.fake_env)
req_data = self.session_adapter.last_request.json() self.client.create(name=env_name,
release_id=release_id,
network_provider=net,
net_segment_type=nst)
self.assertEqual(rm.POST, self.session_adapter.last_request.method) req_data = matcher.last_request.json()
self.assertEqual(self.res_uri, self.session_adapter.last_request.path)
self.assertTrue(matcher.called)
# TODO(romcheg): deployment mode requires investigation
self.assertEqual(release_id, req_data['release_id']) self.assertEqual(release_id, req_data['release_id'])
self.assertEqual(node_name, req_data['name']) self.assertEqual(env_name, req_data['name'])
self.assertEqual(nst, req_data['net_segment_type']) self.assertEqual(nst, req_data['net_segment_type'])
self.assertEqual(net, req_data['net_provider'])
def test_env_create_no_nst_neutron(self): def test_env_create_no_nst_neutron(self):
node_name = 'test_node' node_name = 'test_node'
@@ -102,35 +110,42 @@ class TestEnvFacade(test_api.BaseLibTest):
def test_env_deploy(self, m_init): def test_env_deploy(self, m_init):
env_id = 42 env_id = 42
expected_uri = self.get_object_uri(self.res_uri, env_id, '/changes') expected_uri = self.get_object_uri(self.res_uri, env_id, '/changes')
matcher = self.m_request.put(expected_uri, json={})
self.client.deploy_changes(env_id) self.client.deploy_changes(env_id)
self.assertEqual(rm.PUT, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
@mock.patch.object(base_object.BaseObject, 'init_with_data') @mock.patch.object(base_object.BaseObject, 'init_with_data')
def test_env_upgrade(self, m_init): def test_env_upgrade(self, m_init):
env_id = 42 env_id = 42
release_id = 10 release_id = 10
expected_uri = self.get_object_uri(self.res_uri, env_id, '/update/')
node_uri = self.get_object_uri(self.res_uri, env_id)
update_uri = self.get_object_uri(self.res_uri, env_id, '/update/')
put_matcher = self.m_request.put(node_uri, json=self.fake_env)
update_matcher = self.m_request.put(update_uri, json={})
self.client.upgrade(env_id, release_id) self.client.upgrade(env_id, release_id)
self.assertEqual(rm.PUT, self.session_adapter.last_request.method) self.assertTrue(put_matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path) self.assertTrue(update_matcher.called)
@mock.patch.object(base_object.BaseObject, 'init_with_data') @mock.patch.object(base_object.BaseObject, 'init_with_data')
def test_env_update(self, m_init): def test_env_update(self, m_init):
env_id = 42 env_id = 42
expected_uri = self.get_object_uri(self.res_uri, env_id) expected_uri = self.get_object_uri(self.res_uri, env_id)
self.client.update(env_id, name="new_name") get_matcher = self.m_request.get(expected_uri, json=self.fake_env)
req_data = self.session_adapter.request_history[0].json() upd_matcher = self.m_request.put(expected_uri, json=self.fake_env)
self.assertEqual(rm.PUT, self.client.update(env_id, name="new_name")
self.session_adapter.request_history[0].method)
self.assertEqual(expected_uri, self.assertTrue(expected_uri, get_matcher.called)
self.session_adapter.request_history[0].path) self.assertTrue(expected_uri, upd_matcher.called)
req_data = upd_matcher.last_request.json()
self.assertEqual('new_name', req_data['name']) self.assertEqual('new_name', req_data['name'])
def test_env_update_wrong_attribute(self): def test_env_update_wrong_attribute(self):
@@ -150,19 +165,22 @@ class TestEnvFacade(test_api.BaseLibTest):
expected_uri = self.get_object_uri(self.res_uri, expected_uri = self.get_object_uri(self.res_uri,
env_id, '/assignment/') env_id, '/assignment/')
matcher = self.m_request.post(expected_uri, json={})
self.client.add_nodes(env_id, nodes, roles) self.client.add_nodes(env_id, nodes, roles)
self.assertEqual(rm.POST, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
for assignment in self.session_adapter.last_request.json(): for assignment in matcher.last_request.json():
# Check whether all assignments are expected # Check whether all assignments are expected
self.assertIn(assignment, expected_body) self.assertIn(assignment, expected_body)
def test_env_spawn_vms(self): def test_env_spawn_vms(self):
env_id = 10 env_id = 10
expected_uri = '/api/v1/clusters/{0}/spawn_vms/'.format(env_id) expected_uri = '/api/v1/clusters/{0}/spawn_vms/'.format(env_id)
matcher = self.m_request.put(expected_uri, json={})
self.client.spawn_vms(env_id) self.client.spawn_vms(env_id)
self.assertEqual(rm.PUT, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)

View File

@@ -14,9 +14,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import requests_mock as rm
import fuelclient import fuelclient
from fuelclient.tests import utils
from fuelclient.tests.v2.unit.lib import test_api from fuelclient.tests.v2.unit.lib import test_api
@@ -28,10 +27,13 @@ class TestFuelVersionFacade(test_api.BaseLibTest):
self.version = 'v1' self.version = 'v1'
self.res_uri = '/api/{version}/version/'.format(version=self.version) self.res_uri = '/api/{version}/version/'.format(version=self.version)
self.fake_version = utils.get_fake_fuel_version()
self.client = fuelclient.get_client('fuel-version', self.version) self.client = fuelclient.get_client('fuel-version', self.version)
def test_fuel_version(self): def test_fuel_version(self):
matcher = self.m_request.get(self.res_uri, json=self.fake_version)
self.client.get_all() self.client.get_all()
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(self.res_uri, self.session_adapter.last_request.path)

View File

@@ -14,10 +14,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import json
import requests_mock as rm
import fuelclient import fuelclient
from fuelclient.tests import utils
from fuelclient.tests.v2.unit.lib import test_api from fuelclient.tests.v2.unit.lib import test_api
@@ -29,31 +27,38 @@ class TestNodeFacade(test_api.BaseLibTest):
self.version = 'v1' self.version = 'v1'
self.res_uri = '/api/{version}/nodes/'.format(version=self.version) self.res_uri = '/api/{version}/nodes/'.format(version=self.version)
self.fake_node = utils.get_fake_node()
self.fake_nodes = [utils.get_fake_node() for _ in range(10)]
self.client = fuelclient.get_client('node', self.version) self.client = fuelclient.get_client('node', self.version)
def test_node_list(self): def test_node_list(self):
matcher = self.m_request.get(self.res_uri, json=self.fake_nodes)
self.client.get_all() self.client.get_all()
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(self.res_uri, self.session_adapter.last_request.path)
def test_node_show(self): def test_node_show(self):
node_id = 42 node_id = 42
expected_uri = self.get_object_uri(self.res_uri, node_id) expected_uri = self.get_object_uri(self.res_uri, node_id)
matcher = self.m_request.get(expected_uri, json=self.fake_node)
self.client.get_by_id(node_id) self.client.get_by_id(node_id)
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
def test_node_vms_list(self): def test_node_vms_list(self):
node_id = 42 node_id = 42
expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id) expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id)
fake_vms = [{'id': 1, 'opt2': 'val2'},
{'id': 2, 'opt4': 'val4'}]
matcher = self.m_request.get(expected_uri, json=fake_vms)
self.client.get_node_vms_conf(node_id) self.client.get_node_vms_conf(node_id)
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
def test_node_vms_create(self): def test_node_vms_create(self):
config = [{'id': 1, 'opt2': 'val2'}, config = [{'id': 1, 'opt2': 'val2'},
@@ -61,13 +66,14 @@ class TestNodeFacade(test_api.BaseLibTest):
node_id = 42 node_id = 42
expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id) expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id)
expected_body = json.dumps({'vms_conf': config}) expected_body = {'vms_conf': config}
matcher = self.m_request.put(expected_uri, json=expected_body)
self.client.node_vms_create(node_id, config) self.client.node_vms_create(node_id, config)
self.assertEqual(rm.PUT, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path) self.assertEqual(expected_body, matcher.last_request.json())
self.assertEqual(expected_body, self.session_adapter.last_request.body)
def test_node_set_hostname(self): def test_node_set_hostname(self):
node_id = 42 node_id = 42
@@ -75,8 +81,9 @@ class TestNodeFacade(test_api.BaseLibTest):
data = {"hostname": hostname} data = {"hostname": hostname}
expected_uri = self.get_object_uri(self.res_uri, node_id) expected_uri = self.get_object_uri(self.res_uri, node_id)
matcher = self.m_request.put(expected_uri, json=data)
self.client.update(node_id, **data) self.client.update(node_id, **data)
self.assertEqual(rm.PUT, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path) self.assertEqual(data, matcher.last_request.json())
self.assertEqual(data, self.session_adapter.last_request.json())

View File

@@ -14,9 +14,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import requests_mock as rm
import fuelclient import fuelclient
from fuelclient.tests import utils
from fuelclient.tests.v2.unit.lib import test_api from fuelclient.tests.v2.unit.lib import test_api
@@ -28,19 +27,25 @@ class TestTaskFacade(test_api.BaseLibTest):
self.version = 'v1' self.version = 'v1'
self.res_uri = '/api/{version}/tasks/'.format(version=self.version) self.res_uri = '/api/{version}/tasks/'.format(version=self.version)
self.fake_task = utils.get_fake_task()
self.fake_tasks = [utils.get_fake_task() for _ in range(10)]
self.client = fuelclient.get_client('task', self.version) self.client = fuelclient.get_client('task', self.version)
def test_node_list(self): def test_task_list(self):
matcher = self.m_request.get(self.res_uri, json=self.fake_task)
self.client.get_all() self.client.get_all()
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(self.res_uri, matcher.called)
self.assertEqual(self.res_uri, self.session_adapter.last_request.path)
def test_node_show(self): def test_task_show(self):
task_id = 42 task_id = 42
expected_uri = self.get_object_uri(self.res_uri, task_id) expected_uri = self.get_object_uri(self.res_uri, task_id)
matcher = self.m_request.get(expected_uri, json=self.fake_tasks)
self.client.get_by_id(task_id) self.client.get_by_id(task_id)
self.assertEqual(rm.GET, self.session_adapter.last_request.method) self.assertTrue(matcher.called)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)