From 14a350d0139226c035b5a112d0a53eef3fe2686b Mon Sep 17 00:00:00 2001 From: Ivan Kolodyazhny Date: Fri, 6 Oct 2017 16:36:08 +0300 Subject: [PATCH] Switch Cinder-related tests to mock This patch changes mox to mock for the following test module: * openstack_dashboard/dashboards/admin/volumes/tests.py Change-Id: Id487feb397207b3544c9398a446077e3f6a39b1a Partially-Implements: blueprint mock-framework-in-unit-tests --- .../dashboards/admin/volumes/tests.py | 307 +++++++++--------- openstack_dashboard/test/helpers.py | 7 + 2 files changed, 156 insertions(+), 158 deletions(-) diff --git a/openstack_dashboard/dashboards/admin/volumes/tests.py b/openstack_dashboard/dashboards/admin/volumes/tests.py index 24e73d1d34..56913a8712 100644 --- a/openstack_dashboard/dashboards/admin/volumes/tests.py +++ b/openstack_dashboard/dashboards/admin/volumes/tests.py @@ -16,10 +16,9 @@ import copy from django.conf import settings from django.core.urlresolvers import reverse -from django import http from django.test.utils import override_settings from django.utils.http import urlunquote -from mox3.mox import IsA +import mock from openstack_dashboard import api from openstack_dashboard.api import cinder @@ -44,76 +43,77 @@ class VolumeTests(test.BaseAdminViewTests): del att['instance'] super(VolumeTests, self).tearDown() - @test.create_stubs({api.nova: ('server_list', 'server_get'), - cinder: ('volume_list_paged', - 'volume_snapshot_list'), - keystone: ('tenant_list',)}) - def _test_index(self, instanceless_volumes=False): + @mock.patch.object(keystone, 'tenant_list') + @mock.patch.object(cinder, 'volume_snapshot_list') + @mock.patch.object(cinder, 'volume_list_paged') + @mock.patch.object(api.nova, 'server_list') + def _test_index(self, instanceless_volumes, mock_server_list, + mock_volume_list, mock_snapshot_list, mock_tenant_list): volumes = self.cinder_volumes.list() if instanceless_volumes: for volume in volumes: volume.attachments = [] - else: - server = self.servers.first() - cinder.volume_list_paged(IsA(http.HttpRequest), sort_dir="desc", - marker=None, paginate=True, - search_opts={'all_tenants': True})\ - .AndReturn([volumes, False, False]) - cinder.volume_snapshot_list(IsA(http.HttpRequest), search_opts={ - 'all_tenants': True}).AndReturn([]) + mock_volume_list.return_value = [volumes, False, False] + mock_snapshot_list.return_value = [] + if not instanceless_volumes: - api.nova.server_get(IsA(http.HttpRequest), - server.id).AndReturn(server) - api.nova.server_list(IsA(http.HttpRequest), search_opts={ - 'all_tenants': True}, detailed=False) \ - .AndReturn([self.servers.list(), False]) - keystone.tenant_list(IsA(http.HttpRequest)) \ - .AndReturn([self.tenants.list(), False]) + mock_server_list.return_value = [self.servers.list(), False] + + mock_tenant_list.return_value = [[self.tenants.list(), False]] - self.mox.ReplayAll() res = self.client.get(INDEX_URL) + if not instanceless_volumes: + mock_server_list.assert_called_once_with( + test.IsHttpRequest(), search_opts={'all_tenants': True}) + mock_volume_list.assert_called_once_with( + test.IsHttpRequest(), sort_dir="desc", marker=None, paginate=True, + search_opts={'all_tenants': True}) + mock_snapshot_list.assert_called_once_with( + test.IsHttpRequest(), search_opts={'all_tenants': True}) + mock_tenant_list.assert_called_once() self.assertTemplateUsed(res, 'horizon/common/_data_table_view.html') volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, self.cinder_volumes.list()) def test_index_without_attachments(self): - self._test_index(instanceless_volumes=True) + self._test_index(True) def test_index_with_attachments(self): - self._test_index(instanceless_volumes=False) + self._test_index(False) - @test.create_stubs({api.nova: ('server_list', 'server_get'), - cinder: ('volume_list_paged', - 'volume_snapshot_list'), - keystone: ('tenant_list',)}) + @mock.patch.object(keystone, 'tenant_list') + @mock.patch.object(cinder, 'volume_snapshot_list') + @mock.patch.object(cinder, 'volume_list_paged') + @mock.patch.object(api.nova, 'server_list') def _test_index_paginated(self, marker, sort_dir, volumes, url, - has_more, has_prev): + has_more, has_prev, mock_server_list, + mock_volume_list, mock_snapshot_list, + mock_tenant_list): vol_snaps = self.cinder_volume_snapshots.list() - server = self.servers.first() - cinder.volume_list_paged(IsA(http.HttpRequest), sort_dir=sort_dir, - marker=marker, paginate=True, - search_opts={'all_tenants': True}) \ - .AndReturn([volumes, has_more, has_prev]) - api.cinder.volume_snapshot_list( - IsA(http.HttpRequest), search_opts=None).AndReturn(vol_snaps) - api.nova.server_list(IsA(http.HttpRequest), search_opts={ - 'all_tenants': True}, detailed=False) \ - .AndReturn([self.servers.list(), False]) - api.nova.server_get(IsA(http.HttpRequest), - server.id).AndReturn(server) - keystone.tenant_list(IsA(http.HttpRequest)) \ - .AndReturn([self.tenants.list(), False]) - self.mox.ReplayAll() + mock_volume_list.return_value = [volumes, has_more, has_prev] + mock_snapshot_list.return_value = vol_snaps + mock_server_list.return_value = [self.servers.list(), False] + mock_tenant_list.return_value = [self.tenants.list(), False] res = self.client.get(urlunquote(url)) + mock_server_list.assert_called_once_with( + test.IsHttpRequest(), search_opts={'all_tenants': True}) + mock_volume_list.assert_called_once_with(test.IsHttpRequest(), + sort_dir=sort_dir, + marker=marker, paginate=True, + search_opts={ + 'all_tenants': True}) + mock_snapshot_list.assert_called_once_with( + test.IsHttpRequest(), search_opts={'all_tenants': True}) + mock_tenant_list.assert_called_once() + self.assertTemplateUsed(res, 'horizon/common/_data_table_view.html') self.assertEqual(res.status_code, 200) - self.mox.UnsetStubs() return res @override_settings(FILTER_DATA_FIRST={'admin.volumes': True}) @@ -123,7 +123,7 @@ class VolumeTests(test.BaseAdminViewTests): volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, []) - def ensure_attachments_exist(self, volumes): + def _ensure_attachments_exist(self, volumes): volumes = copy.copy(volumes) for volume in volumes: if not volume.attachments: @@ -134,14 +134,14 @@ class VolumeTests(test.BaseAdminViewTests): @override_settings(API_RESULT_PAGE_SIZE=2) def test_index_paginated(self): size = settings.API_RESULT_PAGE_SIZE - mox_volumes = self.ensure_attachments_exist(self.cinder_volumes.list()) + mox_volumes = self._ensure_attachments_exist( + self.cinder_volumes.list()) # get first page expected_volumes = mox_volumes[:size] url = INDEX_URL - res = self._test_index_paginated(marker=None, sort_dir="desc", - volumes=expected_volumes, url=url, - has_more=True, has_prev=False) + res = self._test_index_paginated(None, "desc", expected_volumes, url, + True, False) volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, expected_volumes) @@ -150,9 +150,8 @@ class VolumeTests(test.BaseAdminViewTests): marker = expected_volumes[0].id next = volume_tables.VolumesTable._meta.pagination_param url = INDEX_URL + "?%s=%s" % (next, marker) - res = self._test_index_paginated(marker=marker, sort_dir="desc", - volumes=expected_volumes, url=url, - has_more=True, has_prev=True) + res = self._test_index_paginated(marker, "desc", expected_volumes, url, + True, True) volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, expected_volumes) @@ -161,25 +160,24 @@ class VolumeTests(test.BaseAdminViewTests): marker = expected_volumes[0].id next = volume_tables.VolumesTable._meta.pagination_param url = INDEX_URL + "?%s=%s" % (next, marker) - res = self._test_index_paginated(marker=marker, sort_dir="desc", - volumes=expected_volumes, url=url, - has_more=False, has_prev=True) + res = self._test_index_paginated(marker, "desc", expected_volumes, url, + False, True) volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, expected_volumes) @override_settings(API_RESULT_PAGE_SIZE=2) def test_index_paginated_prev(self): size = settings.API_RESULT_PAGE_SIZE - mox_volumes = self.ensure_attachments_exist(self.cinder_volumes.list()) + mox_volumes = self._ensure_attachments_exist( + self.cinder_volumes.list()) # prev from some page expected_volumes = mox_volumes[size:2 * size] marker = mox_volumes[0].id prev = volume_tables.VolumesTable._meta.prev_pagination_param url = INDEX_URL + "?%s=%s" % (prev, marker) - res = self._test_index_paginated(marker=marker, sort_dir="asc", - volumes=expected_volumes, url=url, - has_more=False, has_prev=True) + res = self._test_index_paginated(marker, "asc", expected_volumes, url, + False, True) volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, expected_volumes) @@ -188,35 +186,36 @@ class VolumeTests(test.BaseAdminViewTests): marker = mox_volumes[0].id prev = volume_tables.VolumesTable._meta.prev_pagination_param url = INDEX_URL + "?%s=%s" % (prev, marker) - res = self._test_index_paginated(marker=marker, sort_dir="asc", - volumes=expected_volumes, url=url, - has_more=True, has_prev=False) + res = self._test_index_paginated(marker, "asc", expected_volumes, url, + True, False) volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, expected_volumes) - @test.create_stubs({cinder: ('volume_reset_state', - 'volume_get')}) - def test_update_volume_status(self): + @mock.patch.object(cinder, 'volume_get') + @mock.patch.object(cinder, 'volume_reset_state') + def test_update_volume_status(self, mock_reset, mock_volume_get): volume = self.volumes.first() formData = {'status': 'error'} - cinder.volume_get(IsA(http.HttpRequest), volume.id).AndReturn(volume) - cinder.volume_reset_state(IsA(http.HttpRequest), - volume.id, - formData['status']) - self.mox.ReplayAll() + mock_volume_get.return_value = volume res = self.client.post( reverse('horizon:admin:volumes:update_status', args=(volume.id,)), formData) + + mock_reset.assert_called_once_with(test.IsHttpRequest(), + volume.id, formData['status']) + mock_volume_get.assert_called_once_with(test.IsHttpRequest(), + volume.id) self.assertNoFormErrors(res) - @test.create_stubs({cinder: ('volume_manage', - 'volume_type_list', - 'availability_zone_list', - 'extension_supported')}) - def test_manage_volume(self): + @mock.patch.object(cinder, 'extension_supported') + @mock.patch.object(cinder, 'availability_zone_list') + @mock.patch.object(cinder, 'volume_type_list') + @mock.patch.object(cinder, 'volume_manage') + def test_manage_volume(self, mock_manage, mock_type_list, mock_az_list, + mock_extension): metadata = {'key': u'k1', 'value': u'v1'} formData = {'host': 'host-1', @@ -228,18 +227,17 @@ class VolumeTests(test.BaseAdminViewTests): 'availability_zone': 'nova', 'metadata': metadata['key'] + '=' + metadata['value'], 'bootable': False} - cinder.volume_type_list( - IsA(http.HttpRequest)). \ - AndReturn(self.cinder_volume_types.list()) - cinder.availability_zone_list( - IsA(http.HttpRequest)). \ - AndReturn(self.availability_zones.list()) - cinder.extension_supported( - IsA(http.HttpRequest), - 'AvailabilityZones'). \ - AndReturn(True) - cinder.volume_manage( - IsA(http.HttpRequest), + + mock_type_list.return_value = self.cinder_volume_types.list() + mock_az_list.return_value = self.availability_zones.list() + mock_extension.return_value = True + + res = self.client.post( + reverse('horizon:admin:volumes:manage'), + formData) + + mock_manage.assert_called_once_with( + test.IsHttpRequest(), host=formData['host'], identifier=formData['identifier'], id_type=formData['id_type'], @@ -249,15 +247,15 @@ class VolumeTests(test.BaseAdminViewTests): availability_zone=formData['availability_zone'], metadata={metadata['key']: metadata['value']}, bootable=formData['bootable']) - self.mox.ReplayAll() - res = self.client.post( - reverse('horizon:admin:volumes:manage'), - formData) + mock_type_list.assert_called_once() + mock_az_list.assert_called_once() + mock_extension.assert_called_once_with(test.IsHttpRequest(), + 'AvailabilityZones') self.assertNoFormErrors(res) - @test.create_stubs({cinder: ('volume_unmanage', - 'volume_get')}) - def test_unmanage_volume(self): + @mock.patch.object(cinder, 'volume_get') + @mock.patch.object(cinder, 'volume_unmanage') + def test_unmanage_volume(self, mock_unmanage, mock_get): # important - need to get the v2 cinder volume which has host data volume_list = [x for x in self.cinder_volumes.list() if x.name == 'v2_volume'] @@ -266,111 +264,105 @@ class VolumeTests(test.BaseAdminViewTests): 'host_name': 'host@backend-name#pool', 'volume_id': volume.id} - cinder.volume_get(IsA(http.HttpRequest), volume.id).AndReturn(volume) - cinder.volume_unmanage(IsA(http.HttpRequest), volume.id). \ - AndReturn(volume) - self.mox.ReplayAll() + mock_get.return_value = volume + mock_unmanage.return_value = volume + res = self.client.post( reverse('horizon:admin:volumes:unmanage', args=(volume.id,)), formData) + + mock_unmanage.assert_called_once_with(test.IsHttpRequest(), volume.id) + mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id) self.assertNoFormErrors(res) - @test.create_stubs({cinder: ('pool_list', - 'volume_get',)}) - def test_volume_migrate_get(self): + @mock.patch.object(cinder, 'volume_get') + @mock.patch.object(cinder, 'pool_list') + def test_volume_migrate_get(self, mock_pool, mock_get): volume = self.cinder_volumes.get(name='v2_volume') - cinder.volume_get(IsA(http.HttpRequest), volume.id) \ - .AndReturn(volume) - cinder.pool_list(IsA(http.HttpRequest)) \ - .AndReturn(self.cinder_pools.list()) - self.mox.ReplayAll() + mock_pool.return_value = self.cinder_pools.list() + mock_get.return_value = volume url = reverse('horizon:admin:volumes:migrate', args=[volume.id]) res = self.client.get(url) + mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id) + mock_pool.assert_called_once() self.assertTemplateUsed(res, 'admin/volumes/migrate_volume.html') - @test.create_stubs({cinder: ('volume_get',)}) - def test_volume_migrate_get_volume_get_exception(self): + @mock.patch.object(cinder, 'volume_get') + def test_volume_migrate_get_volume_get_exception(self, mock_get): volume = self.cinder_volumes.get(name='v2_volume') - cinder.volume_get(IsA(http.HttpRequest), volume.id) \ - .AndRaise(self.exceptions.cinder) - - self.mox.ReplayAll() + mock_get.side_effect = self.exceptions.cinder url = reverse('horizon:admin:volumes:migrate', args=[volume.id]) res = self.client.get(url) + mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id) self.assertRedirectsNoFollow(res, INDEX_URL) - @test.create_stubs({cinder: ('pool_list', - 'volume_get',)}) - def test_volume_migrate_list_pool_get_exception(self): + @mock.patch.object(cinder, 'volume_get') + @mock.patch.object(cinder, 'pool_list') + def test_volume_migrate_list_pool_get_exception(self, mock_pool, mock_get): volume = self.cinder_volumes.get(name='v2_volume') - cinder.volume_get(IsA(http.HttpRequest), volume.id) \ - .AndReturn(volume) - cinder.pool_list(IsA(http.HttpRequest)) \ - .AndRaise(self.exceptions.cinder) - self.mox.ReplayAll() + mock_get.return_value = volume + mock_pool.side_effect = self.exceptions.cinder + url = reverse('horizon:admin:volumes:migrate', args=[volume.id]) res = self.client.get(url) + mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id) + mock_pool.assert_called_once() self.assertRedirectsNoFollow(res, INDEX_URL) - @test.create_stubs({cinder: ('pool_list', - 'volume_get', - 'volume_migrate',)}) - def test_volume_migrate_post(self): + @mock.patch.object(cinder, 'volume_migrate') + @mock.patch.object(cinder, 'volume_get') + @mock.patch.object(cinder, 'pool_list') + def test_volume_migrate_post(self, mock_pool, mock_get, mock_migtate): volume = self.cinder_volumes.get(name='v2_volume') host = self.cinder_pools.first().name - cinder.volume_get(IsA(http.HttpRequest), volume.id) \ - .AndReturn(volume) - cinder.pool_list(IsA(http.HttpRequest)) \ - .AndReturn(self.cinder_pools.list()) - cinder.volume_migrate(IsA(http.HttpRequest), - volume.id, - host, - False) \ - .AndReturn(None) - - self.mox.ReplayAll() + mock_get.return_value = volume + mock_pool.return_value = self.cinder_pools.list() + mock_migtate.return_value = None url = reverse('horizon:admin:volumes:migrate', args=[volume.id]) res = self.client.post(url, {'host': host, 'volume_id': volume.id}) + + mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id) + mock_pool.assert_called_once() + mock_migtate.assert_called_once_with(test.IsHttpRequest(), + volume.id, host, False) self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @test.create_stubs({cinder: ('pool_list', - 'volume_get', - 'volume_migrate',)}) - def test_volume_migrate_post_api_exception(self): + @mock.patch.object(cinder, 'volume_migrate') + @mock.patch.object(cinder, 'volume_get') + @mock.patch.object(cinder, 'pool_list') + def test_volume_migrate_post_api_exception(self, mock_pool, mock_get, + mock_migtate): volume = self.cinder_volumes.get(name='v2_volume') host = self.cinder_pools.first().name - cinder.volume_get(IsA(http.HttpRequest), volume.id) \ - .AndReturn(volume) - cinder.pool_list(IsA(http.HttpRequest)) \ - .AndReturn(self.cinder_pools.list()) - cinder.volume_migrate(IsA(http.HttpRequest), - volume.id, - host, - False) \ - .AndRaise(self.exceptions.cinder) - - self.mox.ReplayAll() + mock_get.return_value = volume + mock_pool.return_value = self.cinder_pools.list() + mock_migtate.side_effect = self.exceptions.cinder url = reverse('horizon:admin:volumes:migrate', args=[volume.id]) res = self.client.post(url, {'host': host, 'volume_id': volume.id}) + + mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id) + mock_pool.assert_called_once() + mock_migtate.assert_called_once_with(test.IsHttpRequest(), volume.id, + host, False) self.assertRedirectsNoFollow(res, INDEX_URL) def test_get_volume_status_choices_without_current(self): @@ -381,16 +373,15 @@ class VolumeTests(test.BaseAdminViewTests): self.assertNotIn(current_status, [status[0] for status in status_choices]) - @test.create_stubs({cinder: ('volume_get',)}) - def test_update_volume_status_get(self): + @mock.patch.object(cinder, 'volume_get') + def test_update_volume_status_get(self, mock_get): volume = self.cinder_volumes.get(name='v2_volume') - cinder.volume_get(IsA(http.HttpRequest), volume.id) \ - .AndReturn(volume) - - self.mox.ReplayAll() + mock_get.return_value = volume url = reverse('horizon:admin:volumes:update_status', args=[volume.id]) res = self.client.get(url) status_option = "" % volume.status + + mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id) self.assertNotContains(res, status_option) diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py index f2c61056eb..1b8fe87614 100644 --- a/openstack_dashboard/test/helpers.py +++ b/openstack_dashboard/test/helpers.py @@ -30,6 +30,7 @@ from django.conf import settings from django.contrib.messages.storage import default_storage from django.core.handlers import wsgi from django.core import urlresolvers +from django import http as http_request from django.test.client import RequestFactory from django.test import utils as django_test_utils from django.utils import http @@ -693,3 +694,9 @@ def mock_factory(r): mocked = mock_obj_to_dict(r) mocked.configure_mock(**r) return mocked + + +class IsHttpRequest(object): + """Class to compare param is django.http.HttpRequest.""" + def __eq__(self, other): + return isinstance(other, http_request.HttpRequest)