From fbbd58a45919c654e13ab7d284ddfa604f989cd2 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Tue, 17 Jul 2018 11:32:41 -0400 Subject: [PATCH] Remove mox3 completely The porting of mock is complete. This fullfills the community goal 200~"Remove Use of mox/mox3 for Testing" set for Rocky: https://governance.openstack.org/tc/goals/rocky/mox_removal.html This commit does the following code: - Remove dead code that was previously used by mox. - Raise the requirement to the Rocky M2 relase of Horizon. - Convert the clients to use mock. Change-Id: I33521b4bc8e873d50b1d2390e544eea0923dca4f Signed-off-by: Chuck Short --- heat_dashboard/test/helpers.py | 75 +--------- heat_dashboard/test/tests/api/test_heat.py | 140 ++++++++---------- .../test/tests/content/test_resource_types.py | 2 - .../test/tests/content/test_stacks.py | 6 - .../tests/content/test_template_generator.py | 2 - lower-constraints.txt | 1 - test-requirements.txt | 1 - 7 files changed, 71 insertions(+), 156 deletions(-) diff --git a/heat_dashboard/test/helpers.py b/heat_dashboard/test/helpers.py index 89da24ca..5fb81553 100644 --- a/heat_dashboard/test/helpers.py +++ b/heat_dashboard/test/helpers.py @@ -16,7 +16,6 @@ # License for the specific language governing permissions and limitations # under the License. -from functools import wraps from importlib import import_module import os import traceback @@ -59,61 +58,6 @@ IsA = helpers.IsA IsHttpRequest = helpers.IsHttpRequest -def create_stubs(stubs_to_create=None): - """decorator to simplify setting up multiple stubs at once via mox - - :param stubs_to_create: methods to stub in one or more modules - :type stubs_to_create: dict - - The keys are python paths to the module containing the methods to mock. - - To mock a method in openstack_dashboard/api/nova.py, the key is:: - - api.nova - - The values are either a tuple or list of methods to mock in the module - indicated by the key. - - For example:: - - ('server_list',) - -or- - ('flavor_list', 'server_list',) - -or- - ['flavor_list', 'server_list'] - - Additionally, multiple modules can be mocked at once:: - - { - api.nova: ('flavor_list', 'server_list'), - api.glance: ('image_list_detailed',), - } - - """ - if stubs_to_create is None: - stubs_to_create = {} - if not isinstance(stubs_to_create, dict): - raise TypeError("create_stub must be passed a dict, but a %s was " - "given." % type(stubs_to_create).__name__) - - def inner_stub_out(fn): - @wraps(fn) - def instance_stub_out(self, *args, **kwargs): - for key in stubs_to_create: - if not (isinstance(stubs_to_create[key], tuple) or - isinstance(stubs_to_create[key], list)): - raise TypeError("The values of the create_stub " - "dict must be lists or tuples, but " - "is a %s." - % type(stubs_to_create[key]).__name__) - - for value in stubs_to_create[key]: - self.mox.StubOutWithMock(key, value) - return fn(self, *args, **kwargs) - return instance_stub_out - return inner_stub_out - - def _apply_panel_mocks(patchers=None): """Global mocks on panels that get called on all views.""" if patchers is None: @@ -172,10 +116,6 @@ class TestCase(horizon_helpers.TestCase): # boolean variable to store failures missing_mocks = False - # heat-dashboard depends on mox and we need to declare it. - # horizon UT disables mox by default now. - use_mox = True - def fake_conn_request(self): # print a stacktrace to illustrate where the unmocked API call # is being made from @@ -379,7 +319,6 @@ class BaseAdminViewTests(TestCase): For testing admin-only views and functionality. """ - use_mox = True def setActiveUser(self, *args, **kwargs): if "roles" not in kwargs: @@ -404,7 +343,6 @@ class APITestCase(TestCase): For use with tests which deal with the underlying clients rather than stubbing out the openstack_dashboard.api.* methods. """ - use_mox = True def setUp(self): super(APITestCase, self).setUp() @@ -434,7 +372,7 @@ class APITestCase(TestCase): def stub_keystoneclient(self): if not hasattr(self, "keystoneclient"): - self.mox.StubOutWithMock(keystone_client, 'Client') + keystone_client.Client = mock.Mock() # NOTE(saschpe): Mock properties, MockObject.__init__ ignores them: keystone_client.Client.auth_token = 'foo' keystone_client.Client.service_catalog = None @@ -442,25 +380,24 @@ class APITestCase(TestCase): keystone_client.Client.tenant_name = 'tenant_1' keystone_client.Client.management_url = "" keystone_client.Client.__dir__ = lambda: [] - self.keystoneclient = self.mox.CreateMock(keystone_client.Client) + self.keystoneclient = keystone_client.Client return self.keystoneclient def stub_neutronclient(self): if not hasattr(self, "neutronclient"): - self.mox.StubOutWithMock(neutron_client, 'Client') - self.neutronclient = self.mox.CreateMock(neutron_client.Client) + neutron_client.Client = mock.Mock() + self.neutronclient = neutron_client.Client return self.neutronclient def stub_heatclient(self): if not hasattr(self, "heatclient"): - self.mox.StubOutWithMock(heat_client, 'Client') - self.heatclient = self.mox.CreateMock(heat_client.Client) + heat_client.Client = mock.Mock() + self.heatclient = heat_client.Client return self.heatclient # Need this to test both Glance API V1 and V2 versions class ResetImageAPIVersionMixin(object): - use_mox = True def setUp(self): super(ResetImageAPIVersionMixin, self).setUp() diff --git a/heat_dashboard/test/tests/api/test_heat.py b/heat_dashboard/test/tests/api/test_heat.py index 7c7a1a05..f13abd37 100644 --- a/heat_dashboard/test/tests/api/test_heat.py +++ b/heat_dashboard/test/tests/api/test_heat.py @@ -9,6 +9,7 @@ # 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 import six from django.conf import settings @@ -22,20 +23,18 @@ from horizon import exceptions class HeatApiTests(test.APITestCase): - use_mox = True - def test_stack_list(self): api_stacks = self.stacks.list() limit = getattr(settings, 'API_RESULT_LIMIT', 1000) heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.list(limit=limit, - sort_dir='desc', - sort_key='created_at',) \ - .AndReturn(iter(api_stacks)) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.list.return_value = iter(api_stacks) stacks, has_more, has_prev = api.heat.stacks_list(self.request) + heatclient.stacks.list.assert_called_once_with(limit=limit, + sort_dir='desc', + sort_key='created_at', + ) self.assertItemsEqual(stacks, api_stacks) self.assertFalse(has_more) self.assertFalse(has_prev) @@ -49,12 +48,8 @@ class HeatApiTests(test.APITestCase): sort_key = 'size' heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.list(limit=limit, - sort_dir=sort_dir, - sort_key=sort_key,) \ - .AndReturn(iter(api_stacks)) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.list.return_value = iter(api_stacks) stacks, has_more, has_prev = api.heat.stacks_list(self.request, sort_dir=sort_dir, @@ -62,6 +57,8 @@ class HeatApiTests(test.APITestCase): self.assertItemsEqual(stacks, api_stacks) self.assertFalse(has_more) self.assertFalse(has_prev) + heatclient.stacks.list.assert_called_once_with( + limit=limit, sort_dir=sort_dir, sort_key=sort_key,) @override_settings(API_RESULT_PAGE_SIZE=20) def test_stack_list_pagination_less_page_size(self): @@ -71,12 +68,8 @@ class HeatApiTests(test.APITestCase): sort_key = 'created_at' heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.list(limit=page_size + 1, - sort_dir=sort_dir, - sort_key=sort_key,) \ - .AndReturn(iter(api_stacks)) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.list.return_value = iter(api_stacks) stacks, has_more, has_prev = api.heat.stacks_list(self.request, sort_dir=sort_dir, @@ -86,6 +79,10 @@ class HeatApiTests(test.APITestCase): self.assertItemsEqual(stacks, expected_stacks) self.assertFalse(has_more) self.assertFalse(has_prev) + heatclient.stacks.list.assert_called_once_with( + limit=page_size + 1, + sort_dir=sort_dir, + sort_key=sort_key) @override_settings(API_RESULT_PAGE_SIZE=10) def test_stack_list_pagination_equal_page_size(self): @@ -95,12 +92,8 @@ class HeatApiTests(test.APITestCase): sort_key = 'created_at' heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.list(limit=page_size + 1, - sort_dir=sort_dir, - sort_key=sort_key,) \ - .AndReturn(iter(api_stacks)) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.list.return_value = iter(api_stacks) stacks, has_more, has_prev = api.heat.stacks_list(self.request, sort_dir=sort_dir, @@ -110,6 +103,9 @@ class HeatApiTests(test.APITestCase): self.assertItemsEqual(stacks, expected_stacks) self.assertFalse(has_more) self.assertFalse(has_prev) + heatclient.stacks.list.assert_called_once_with( + limit=page_size + 1, sort_dir=sort_dir, + sort_key=sort_key,) @override_settings(API_RESULT_PAGE_SIZE=2) def test_stack_list_pagination_marker(self): @@ -121,13 +117,8 @@ class HeatApiTests(test.APITestCase): api_stacks = self.stacks.list() heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.list(limit=page_size + 1, - marker=marker, - sort_dir=sort_dir, - sort_key=sort_key,) \ - .AndReturn(iter(api_stacks[:page_size + 1])) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.list.return_value = iter(api_stacks[:page_size + 1]) stacks, has_more, has_prev = api.heat.stacks_list(self.request, marker=marker, @@ -139,6 +130,9 @@ class HeatApiTests(test.APITestCase): self.assertItemsEqual(stacks, api_stacks[:page_size]) self.assertTrue(has_more) self.assertTrue(has_prev) + heatclient.stacks.list.assert_called_once_with( + limit=page_size + 1, marker=marker, + sort_dir=sort_dir, sort_key=sort_key,) @override_settings(API_RESULT_PAGE_SIZE=2) def test_stack_list_pagination_marker_prev(self): @@ -150,13 +144,8 @@ class HeatApiTests(test.APITestCase): api_stacks = self.stacks.list() heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.list(limit=page_size + 1, - marker=marker, - sort_dir=sort_dir, - sort_key=sort_key,) \ - .AndReturn(iter(api_stacks[:page_size + 1])) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.list.return_value = iter(api_stacks[:page_size + 1]) stacks, has_more, has_prev = api.heat.stacks_list(self.request, marker=marker, @@ -168,6 +157,9 @@ class HeatApiTests(test.APITestCase): self.assertItemsEqual(stacks, api_stacks[:page_size]) self.assertTrue(has_more) self.assertTrue(has_prev) + heatclient.stacks.list.assert_called_once_with( + limit=page_size + 1, marker=marker, + sort_dir=sort_dir, sort_key=sort_key,) def test_template_get(self): api_stacks = self.stacks.list() @@ -175,29 +167,29 @@ class HeatApiTests(test.APITestCase): mock_data_template = self.stack_templates.list()[0] heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.template(stack_id).AndReturn(mock_data_template) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.template.return_value = mock_data_template template = api.heat.template_get(self.request, stack_id) self.assertEqual(mock_data_template.data, template.data) + heatclient.stacks.template.assert_called_once_with(stack_id) def test_stack_create(self): api_stacks = self.stacks.list() stack = api_stacks[0] heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() + heatclient.stacks = mock.Mock() form_data = {'timeout_mins': 600} password = 'secret' - heatclient.stacks.create(**form_data).AndReturn(stack) - self.mox.ReplayAll() + heatclient.stacks.create.return_value = stack returned_stack = api.heat.stack_create(self.request, password, **form_data) from heatclient.v1 import stacks self.assertIsInstance(returned_stack, stacks.Stack) + heatclient.stack.create_assert_called_once_with(**form_data) def test_stack_update(self): api_stacks = self.stacks.list() @@ -205,11 +197,10 @@ class HeatApiTests(test.APITestCase): stack_id = stack.id heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() + heatclient.stacks = mock.Mock() form_data = {'timeout_mins': 600} password = 'secret' - heatclient.stacks.update(stack_id, **form_data).AndReturn(stack) - self.mox.ReplayAll() + heatclient.stacks.update.return_value = stack returned_stack = api.heat.stack_update(self.request, stack_id, @@ -217,33 +208,35 @@ class HeatApiTests(test.APITestCase): **form_data) from heatclient.v1 import stacks self.assertIsInstance(returned_stack, stacks.Stack) + heatclient.stacks.update.assert_called_once_with( + stack_id, **form_data) def test_snapshot_create(self): stack_id = self.stacks.first().id snapshot_create = self.stack_snapshot_create.list()[0] heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.snapshot(stack_id).AndReturn(snapshot_create) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.snapshot.return_value = snapshot_create returned_snapshot_create_info = api.heat.snapshot_create(self.request, stack_id) self.assertEqual(returned_snapshot_create_info, snapshot_create) + heatclient.stacks.snapshot.assert_called_once_with(stack_id) def test_snapshot_list(self): stack_id = self.stacks.first().id snapshot_list = self.stack_snapshot.list() heatclient = self.stub_heatclient() - heatclient.stacks = self.mox.CreateMockAnything() - heatclient.stacks.snapshot_list(stack_id).AndReturn(snapshot_list) - self.mox.ReplayAll() + heatclient.stacks = mock.Mock() + heatclient.stacks.snapshot_list.return_value = snapshot_list returned_snapshots = api.heat.snapshot_list(self.request, stack_id) self.assertItemsEqual(returned_snapshots, snapshot_list) + heatclient.stacks.snapshot_list.assert_called_once_with(stack_id) def test_get_template_files_with_template_data(self): tmpl = ''' @@ -261,7 +254,8 @@ class HeatApiTests(test.APITestCase): files = api.heat.get_template_files(template_data=tmpl)[0] self.assertEqual(files, expected_files) - def test_get_template_files(self): + @mock.patch.object(six.moves.urllib.request, 'urlopen') + def test_get_template_files(self, mock_request): tmpl = ''' # comment @@ -279,14 +273,14 @@ class HeatApiTests(test.APITestCase): expected_files = {u'http://test.example/example': b'echo "test"'} url = 'http://test.example/example' data = b'echo "test"' - self.mox.StubOutWithMock(six.moves.urllib.request, 'urlopen') - six.moves.urllib.request.urlopen(url).AndReturn( - six.BytesIO(data)) - self.mox.ReplayAll() + mock_request.return_value = six.BytesIO(data) + files = api.heat.get_template_files(template_data=tmpl)[0] self.assertEqual(files, expected_files) + mock_request.assert_called_once_with(url) - def test_get_template_files_with_template_url(self): + @mock.patch.object(six.moves.urllib.request, 'urlopen') + def test_get_template_files_with_template_url(self, mock_request): url = 'https://test.example/example.yaml' data = b''' # comment @@ -302,15 +296,11 @@ class HeatApiTests(test.APITestCase): user_data: get_file: http://test.example/example ''' - url2 = 'http://test.example/example' data2 = b'echo "test"' expected_files = {'http://test.example/example': b'echo "test"'} - self.mox.StubOutWithMock(six.moves.urllib.request, 'urlopen') - six.moves.urllib.request.urlopen(url).AndReturn( - six.BytesIO(data)) - six.moves.urllib.request.urlopen(url2).AndReturn( - six.BytesIO(data2)) - self.mox.ReplayAll() + mock_request.side_effect = \ + [six.BytesIO(data), six.BytesIO(data2)] + files = api.heat.get_template_files(template_url=url)[0] self.assertEqual(files, expected_files) @@ -338,25 +328,25 @@ class HeatApiTests(test.APITestCase): api_template_versions = self.template_versions.list() heatclient = self.stub_heatclient() - heatclient.template_versions = self.mox.CreateMockAnything() - heatclient.template_versions.list().AndReturn(api_template_versions) - self.mox.ReplayAll() + heatclient.template_versions = mock.Mock() + heatclient.template_versions.list.return_value = api_template_versions template_versions = api.heat.template_version_list(self.request) self.assertItemsEqual(template_versions, api_template_versions) + heatclient.template_versions.list.assert_called_once_with() def test_template_function_list(self): template_version = self.template_versions.first().version api_template_functions = self.template_functions.list() heatclient = self.stub_heatclient() - heatclient.template_versions = self.mox.CreateMockAnything() - heatclient.template_versions.get( - template_version).AndReturn(api_template_functions) - self.mox.ReplayAll() + heatclient.template_versions = mock.Mock() + heatclient.template_versions.get.return_value = api_template_functions template_functions = api.heat.template_function_list( self.request, template_version) self.assertItemsEqual(template_functions, api_template_functions) + heatclient.template_versions.get.assert_called_once_with( + template_version) diff --git a/heat_dashboard/test/tests/content/test_resource_types.py b/heat_dashboard/test/tests/content/test_resource_types.py index d18763a2..0419d2bb 100644 --- a/heat_dashboard/test/tests/content/test_resource_types.py +++ b/heat_dashboard/test/tests/content/test_resource_types.py @@ -20,8 +20,6 @@ from heat_dashboard.test.helpers import IsHttpRequest class ResourceTypesTests(test.TestCase): - use_mox = False - @test.create_mocks({api.heat: ('resource_types_list',)}) def test_index(self): self.mock_resource_types_list.return_value = \ diff --git a/heat_dashboard/test/tests/content/test_stacks.py b/heat_dashboard/test/tests/content/test_stacks.py index 4a0401bc..7a8ccfa2 100644 --- a/heat_dashboard/test/tests/content/test_stacks.py +++ b/heat_dashboard/test/tests/content/test_stacks.py @@ -44,8 +44,6 @@ class MockResource(object): class MappingsTests(test.TestCase): - use_mox = False - def test_mappings(self): def assertMappingUrl(url, resource_type, physical_resource_id): @@ -117,8 +115,6 @@ class MappingsTests(test.TestCase): class StackTests(test.TestCase): - use_mox = False - @override_settings(API_RESULT_PAGE_SIZE=2) @test.create_mocks({api.heat: ('stacks_list',)}) def test_index_paginated(self): @@ -876,8 +872,6 @@ class StackTests(test.TestCase): class TemplateFormTests(test.TestCase): - use_mox = False - class SimpleFile(object): def __init__(self, name, data): self.name = name diff --git a/heat_dashboard/test/tests/content/test_template_generator.py b/heat_dashboard/test/tests/content/test_template_generator.py index f5abd5a6..f124ae13 100644 --- a/heat_dashboard/test/tests/content/test_template_generator.py +++ b/heat_dashboard/test/tests/content/test_template_generator.py @@ -22,8 +22,6 @@ from heat_dashboard.test import helpers as test class TemplateGeneratorTests(test.TestCase): - use_mox = False - def test_index(self): self.client.get(reverse('horizon:project:template_generator:index')) self.assertTemplateUsed( diff --git a/lower-constraints.txt b/lower-constraints.txt index 48de39a3..d31751a5 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -46,7 +46,6 @@ MarkupSafe==1.0 mccabe==0.2.1 mock==2.0.0 monotonic==0.6 -mox3==0.20.0 msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 diff --git a/test-requirements.txt b/test-requirements.txt index c820e331..4d9cf462 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -13,6 +13,5 @@ coverage!=4.4,>=4.0 # Apache-2.0 doc8>=0.6.0 # Apache-2.0 flake8-import-order==0.12 # LGPLv3 mock>=2.0.0 # BSD -mox3>=0.20.0 # Apache-2.0 nodeenv>=0.9.4 # BSD testtools>=2.2.0 # MIT