Merge "Drop use_mox from horizon test helpers"
This commit is contained in:
commit
35ac8aac77
@ -1322,7 +1322,8 @@ class DataTable(object):
|
|||||||
# This function should be using django.utils.functional.cached_property
|
# This function should be using django.utils.functional.cached_property
|
||||||
# decorator, but unfortunately due to bug in Django
|
# decorator, but unfortunately due to bug in Django
|
||||||
# https://code.djangoproject.com/ticket/19872 it would make it fail
|
# https://code.djangoproject.com/ticket/19872 it would make it fail
|
||||||
# when being mocked by mox in tests.
|
# when being mocked in tests.
|
||||||
|
# TODO(amotoki): Check if this trick is still required.
|
||||||
if not hasattr(self, '_filtered_data'):
|
if not hasattr(self, '_filtered_data'):
|
||||||
self._filtered_data = self.data
|
self._filtered_data = self.data
|
||||||
if self._meta.filter and self._meta._filter_action:
|
if self._meta.filter and self._meta._filter_action:
|
||||||
@ -1391,6 +1392,7 @@ class DataTable(object):
|
|||||||
except AssertionError:
|
except AssertionError:
|
||||||
# don't trap mox exceptions (which subclass AssertionError)
|
# don't trap mox exceptions (which subclass AssertionError)
|
||||||
# when testing!
|
# when testing!
|
||||||
|
# TODO(amotoki): Check if this trick is still required.
|
||||||
raise
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception("Error while checking action permissions.")
|
LOG.exception("Error while checking action permissions.")
|
||||||
|
@ -63,17 +63,7 @@ except ImportError as e:
|
|||||||
LOG.warning("%s, force WITH_SELENIUM=False", e)
|
LOG.warning("%s, force WITH_SELENIUM=False", e)
|
||||||
os.environ['WITH_SELENIUM'] = ''
|
os.environ['WITH_SELENIUM'] = ''
|
||||||
|
|
||||||
# As of Rocky, we are in the process of removing mox usage.
|
# Makes output of failing tests much easier to read.
|
||||||
# To allow mox-free horizon plugins to consume the test helper,
|
|
||||||
# mox import is now optional. If tests depends on mox,
|
|
||||||
# mox (or mox3) must be declared in test-requirements.txt.
|
|
||||||
try:
|
|
||||||
from mox3 import mox
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Makes output of failing mox tests much easier to read.
|
|
||||||
wsgi.WSGIRequest.__repr__ = lambda self: "<class 'django.http.HttpRequest'>"
|
wsgi.WSGIRequest.__repr__ = lambda self: "<class 'django.http.HttpRequest'>"
|
||||||
|
|
||||||
|
|
||||||
@ -129,23 +119,13 @@ class RequestFactoryWithMessages(RequestFactory):
|
|||||||
class TestCase(django_test.TestCase):
|
class TestCase(django_test.TestCase):
|
||||||
"""Base test case class for Horizon with numerous additional features.
|
"""Base test case class for Horizon with numerous additional features.
|
||||||
|
|
||||||
* The ``mox`` mocking framework via ``self.mox``
|
|
||||||
if ``use_mox`` attribute is set to True.
|
|
||||||
Note that ``use_mox`` defaults to False.
|
|
||||||
* A ``RequestFactory`` class which supports Django's ``contrib.messages``
|
* A ``RequestFactory`` class which supports Django's ``contrib.messages``
|
||||||
framework via ``self.factory``.
|
framework via ``self.factory``.
|
||||||
* A ready-to-go request object via ``self.request``.
|
* A ready-to-go request object via ``self.request``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use_mox = False
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestCase, self).setUp()
|
super(TestCase, self).setUp()
|
||||||
if self.use_mox:
|
|
||||||
LOG.warning("'use_mox' will be dropped at the beginning of "
|
|
||||||
"'Stein' release. If you still depend on mox, "
|
|
||||||
"you must prepare mox environment in your test case.")
|
|
||||||
self.mox = mox.Mox()
|
|
||||||
self._setup_test_data()
|
self._setup_test_data()
|
||||||
self._setup_factory()
|
self._setup_factory()
|
||||||
self._setup_user()
|
self._setup_user()
|
||||||
@ -174,9 +154,6 @@ class TestCase(django_test.TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(TestCase, self).tearDown()
|
super(TestCase, self).tearDown()
|
||||||
if self.use_mox:
|
|
||||||
self.mox.UnsetStubs()
|
|
||||||
self.mox.VerifyAll()
|
|
||||||
del os.environ["HORIZON_TEST_RUN"]
|
del os.environ["HORIZON_TEST_RUN"]
|
||||||
|
|
||||||
def set_permissions(self, permissions=None):
|
def set_permissions(self, permissions=None):
|
||||||
|
@ -5058,7 +5058,7 @@ class InstanceAjaxTests(helpers.TestCase, InstanceTestHelperMixin):
|
|||||||
class ConsoleManagerTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
class ConsoleManagerTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||||
|
|
||||||
def setup_consoles(self):
|
def setup_consoles(self):
|
||||||
# Need to refresh with mocks or will fail since mox do not detect
|
# Need to refresh with mocks or will fail since mock do not detect
|
||||||
# the api_call() as mocked.
|
# the api_call() as mocked.
|
||||||
console.CONSOLES = collections.OrderedDict([
|
console.CONSOLES = collections.OrderedDict([
|
||||||
('VNC', api.nova.server_vnc_console),
|
('VNC', api.nova.server_vnc_console),
|
||||||
|
@ -30,27 +30,12 @@ from django.test import tag
|
|||||||
from django import urls
|
from django import urls
|
||||||
from django.utils import http
|
from django.utils import http
|
||||||
|
|
||||||
from cinderclient import client as cinder_client
|
|
||||||
import glanceclient
|
|
||||||
from keystoneclient.v2_0 import client as keystone_client
|
|
||||||
# As of Rocky, we are in the process of removing mox usage.
|
|
||||||
# To allow mox-free horizon plugins to consume the test helper,
|
|
||||||
# mox import is now optional. If tests depends on mox,
|
|
||||||
# mox (or mox3) must be declared in test-requirements.txt.
|
|
||||||
import mock
|
import mock
|
||||||
try:
|
|
||||||
from mox3 import mox
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
from neutronclient.v2_0 import client as neutron_client
|
|
||||||
from novaclient import api_versions as nova_api_versions
|
|
||||||
from novaclient.v2 import client as nova_client
|
|
||||||
from openstack_auth import user
|
from openstack_auth import user
|
||||||
from openstack_auth import utils
|
from openstack_auth import utils
|
||||||
from requests.packages.urllib3.connection import HTTPConnection
|
from requests.packages.urllib3.connection import HTTPConnection
|
||||||
import six
|
import six
|
||||||
from six import moves
|
from six import moves
|
||||||
from swiftclient import client as swift_client
|
|
||||||
|
|
||||||
from horizon import base
|
from horizon import base
|
||||||
from horizon import conf
|
from horizon import conf
|
||||||
@ -62,7 +47,7 @@ from openstack_dashboard.test.test_data import utils as test_utils
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Makes output of failing mox tests much easier to read.
|
# Makes output of failing tests much easier to read.
|
||||||
wsgi.WSGIRequest.__repr__ = lambda self: "<class 'django.http.HttpRequest'>"
|
wsgi.WSGIRequest.__repr__ = lambda self: "<class 'django.http.HttpRequest'>"
|
||||||
|
|
||||||
# Shortcuts to avoid importing horizon_helpers and for backward compatibility.
|
# Shortcuts to avoid importing horizon_helpers and for backward compatibility.
|
||||||
@ -71,61 +56,6 @@ IsA = horizon_helpers.IsA
|
|||||||
IsHttpRequest = horizon_helpers.IsHttpRequest
|
IsHttpRequest = horizon_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 create_mocks(target_methods):
|
def create_mocks(target_methods):
|
||||||
"""decorator to simplify setting up multiple mocks at once
|
"""decorator to simplify setting up multiple mocks at once
|
||||||
|
|
||||||
@ -245,8 +175,6 @@ class TestCase(horizon_helpers.TestCase):
|
|||||||
docs for
|
docs for
|
||||||
:class:`~openstack_dashboard.test.test_data.utils.TestData`
|
:class:`~openstack_dashboard.test.test_data.utils.TestData`
|
||||||
for more information.
|
for more information.
|
||||||
* The ``mox`` mocking framework via ``self.mox``.
|
|
||||||
if ``use_mox`` attribute is set to True.
|
|
||||||
* A set of request context data via ``self.context``.
|
* A set of request context data via ``self.context``.
|
||||||
* A ``RequestFactory`` class which supports Django's ``contrib.messages``
|
* A ``RequestFactory`` class which supports Django's ``contrib.messages``
|
||||||
framework via ``self.factory``.
|
framework via ``self.factory``.
|
||||||
@ -481,146 +409,17 @@ class BaseAdminViewTests(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class APITestCase(TestCase):
|
class APITestCase(TestCase):
|
||||||
"""Testing APIs.
|
|
||||||
|
|
||||||
For use with tests which deal with the underlying clients rather than
|
|
||||||
stubbing out the openstack_dashboard.api.* methods.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# NOTE: This test class depends on mox but does not declare use_mox = True
|
|
||||||
# to notify mox is no longer recommended.
|
|
||||||
# If a consumer would like to use this class, declare use_mox = True.
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(APITestCase, self).setUp()
|
super(APITestCase, self).setUp()
|
||||||
LOG.warning("APITestCase has been deprecated in favor of mock usage "
|
|
||||||
"and will be removed at the beginning of 'Stein' release. "
|
|
||||||
"Please convert your to use APIMockTestCase instead.")
|
|
||||||
utils.patch_middleware_get_user()
|
utils.patch_middleware_get_user()
|
||||||
|
|
||||||
def fake_keystoneclient(request, admin=False):
|
|
||||||
"""Returns the stub keystoneclient.
|
|
||||||
|
|
||||||
Only necessary because the function takes too many arguments to
|
# APIMockTestCase was introduced to support mox to mock migration smoothly
|
||||||
conveniently be a lambda.
|
# but it turns we have still users of APITestCase.
|
||||||
"""
|
# We keep both for a while.
|
||||||
return self.stub_keystoneclient()
|
# Looking at the usage of these classes, it seems better to drop this one.
|
||||||
|
# TODO(amotoki): Clean up APIMockTestCase usage in horizon plugins.
|
||||||
def fake_glanceclient(request, version='1'):
|
APIMockTestCase = APITestCase
|
||||||
"""Returns the stub glanceclient.
|
|
||||||
|
|
||||||
Only necessary because the function takes too many arguments to
|
|
||||||
conveniently be a lambda.
|
|
||||||
"""
|
|
||||||
return self.stub_glanceclient()
|
|
||||||
|
|
||||||
def fake_novaclient(request, version=None):
|
|
||||||
return self.stub_novaclient()
|
|
||||||
|
|
||||||
# Store the original clients
|
|
||||||
self._original_glanceclient = api.glance.glanceclient
|
|
||||||
self._original_keystoneclient = api.keystone.keystoneclient
|
|
||||||
self._original_novaclient = api.nova.novaclient
|
|
||||||
self._original_neutronclient = api.neutron.neutronclient
|
|
||||||
self._original_cinderclient = api.cinder.cinderclient
|
|
||||||
|
|
||||||
# Replace the clients with our stubs.
|
|
||||||
api.glance.glanceclient = fake_glanceclient
|
|
||||||
api.keystone.keystoneclient = fake_keystoneclient
|
|
||||||
api.nova.novaclient = fake_novaclient
|
|
||||||
api.neutron.neutronclient = lambda request: self.stub_neutronclient()
|
|
||||||
api.cinder.cinderclient = lambda request: self.stub_cinderclient()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super(APITestCase, self).tearDown()
|
|
||||||
api.glance.glanceclient = self._original_glanceclient
|
|
||||||
api.nova.novaclient = self._original_novaclient
|
|
||||||
api.keystone.keystoneclient = self._original_keystoneclient
|
|
||||||
api.neutron.neutronclient = self._original_neutronclient
|
|
||||||
api.cinder.cinderclient = self._original_cinderclient
|
|
||||||
|
|
||||||
def _warn_client(self, service, removal_version):
|
|
||||||
LOG.warning(
|
|
||||||
"APITestCase has been deprecated for %(service)s-related "
|
|
||||||
"tests and will be removerd in '%(removal_version)s' release. "
|
|
||||||
"Please convert your to use APIMockTestCase instead.",
|
|
||||||
{'service': service, 'removal_version': removal_version}
|
|
||||||
)
|
|
||||||
|
|
||||||
def stub_novaclient(self):
|
|
||||||
self._warn_client('nova', 'Stein')
|
|
||||||
if not hasattr(self, "novaclient"):
|
|
||||||
self.mox.StubOutWithMock(nova_client, 'Client')
|
|
||||||
# mock the api_version since MockObject.__init__ ignores it.
|
|
||||||
# The preferred version in the api.nova code is 2 but that's
|
|
||||||
# equivalent to 2.1 now and is the base version that's backward
|
|
||||||
# compatible to 2.0 anyway.
|
|
||||||
api_version = nova_api_versions.APIVersion('2.1')
|
|
||||||
nova_client.Client.api_version = api_version
|
|
||||||
nova_client.Client.projectid = 'fake_project'
|
|
||||||
nova_client.Client.tenant_id = 'fake_tenant'
|
|
||||||
self.novaclient = self.mox.CreateMock(nova_client.Client)
|
|
||||||
return self.novaclient
|
|
||||||
|
|
||||||
def stub_cinderclient(self):
|
|
||||||
self._warn_client('cinder', 'Stein')
|
|
||||||
if not hasattr(self, "cinderclient"):
|
|
||||||
self.mox.StubOutWithMock(cinder_client, 'Client')
|
|
||||||
self.cinderclient = self.mox.CreateMock(cinder_client.Client)
|
|
||||||
return self.cinderclient
|
|
||||||
|
|
||||||
def stub_keystoneclient(self):
|
|
||||||
self._warn_client('keystone', 'Stein')
|
|
||||||
if not hasattr(self, "keystoneclient"):
|
|
||||||
self.mox.StubOutWithMock(keystone_client, 'Client')
|
|
||||||
# NOTE(saschpe): Mock properties, MockObject.__init__ ignores them:
|
|
||||||
keystone_client.Client.auth_token = 'foo'
|
|
||||||
keystone_client.Client.service_catalog = None
|
|
||||||
keystone_client.Client.tenant_id = '1'
|
|
||||||
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)
|
|
||||||
return self.keystoneclient
|
|
||||||
|
|
||||||
def stub_glanceclient(self):
|
|
||||||
self._warn_client('glance', 'Stein')
|
|
||||||
if not hasattr(self, "glanceclient"):
|
|
||||||
self.mox.StubOutWithMock(glanceclient, 'Client')
|
|
||||||
self.glanceclient = self.mox.CreateMock(glanceclient.Client)
|
|
||||||
return self.glanceclient
|
|
||||||
|
|
||||||
def stub_neutronclient(self):
|
|
||||||
self._warn_client('neutron', 'Stein')
|
|
||||||
if not hasattr(self, "neutronclient"):
|
|
||||||
self.mox.StubOutWithMock(neutron_client, 'Client')
|
|
||||||
self.neutronclient = self.mox.CreateMock(neutron_client.Client)
|
|
||||||
return self.neutronclient
|
|
||||||
|
|
||||||
def stub_swiftclient(self, expected_calls=1):
|
|
||||||
self._warn_client('swift', 'Stein')
|
|
||||||
if not hasattr(self, "swiftclient"):
|
|
||||||
self.mox.StubOutWithMock(swift_client, 'Connection')
|
|
||||||
self.swiftclient = self.mox.CreateMock(swift_client.Connection)
|
|
||||||
while expected_calls:
|
|
||||||
swift_client.Connection(None,
|
|
||||||
mox.IgnoreArg(),
|
|
||||||
None,
|
|
||||||
preauthtoken=mox.IgnoreArg(),
|
|
||||||
preauthurl=mox.IgnoreArg(),
|
|
||||||
cacert=None,
|
|
||||||
insecure=False,
|
|
||||||
auth_version="2.0") \
|
|
||||||
.AndReturn(self.swiftclient)
|
|
||||||
expected_calls -= 1
|
|
||||||
return self.swiftclient
|
|
||||||
|
|
||||||
|
|
||||||
class APIMockTestCase(TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(APIMockTestCase, self).setUp()
|
|
||||||
utils.patch_middleware_get_user()
|
|
||||||
|
|
||||||
|
|
||||||
# Need this to test both Glance API V1 and V2 versions
|
# Need this to test both Glance API V1 and V2 versions
|
||||||
|
@ -37,9 +37,6 @@ class RoleAPITests(test.APIMockTestCase):
|
|||||||
|
|
||||||
Verifies that remove_tenant_user is called with the right arguments
|
Verifies that remove_tenant_user is called with the right arguments
|
||||||
after iterating the user's roles.
|
after iterating the user's roles.
|
||||||
|
|
||||||
There are no assertions in this test because the checking is handled
|
|
||||||
by mox in the VerifyAll() call in tearDown().
|
|
||||||
"""
|
"""
|
||||||
keystoneclient = mock_keystoneclient.return_value
|
keystoneclient = mock_keystoneclient.return_value
|
||||||
tenant = self.tenants.first()
|
tenant = self.tenants.first()
|
||||||
@ -67,10 +64,10 @@ class RoleAPITests(test.APIMockTestCase):
|
|||||||
|
|
||||||
role = api.keystone.get_default_role(self.request)
|
role = api.keystone.get_default_role(self.request)
|
||||||
self.assertEqual(self.role, role)
|
self.assertEqual(self.role, role)
|
||||||
# Verify that a second call doesn't hit the API again,
|
|
||||||
# (it would show up in mox as an unexpected method call)
|
|
||||||
role = api.keystone.get_default_role(self.request)
|
|
||||||
|
|
||||||
|
# Verify that a second call doesn't hit the API again,
|
||||||
|
# so we use assert_called_once_with() here.
|
||||||
|
role = api.keystone.get_default_role(self.request)
|
||||||
keystoneclient.roles.list.assert_called_once_with()
|
keystoneclient.roles.list.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user