-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add unit test for coriolis.api.v1.*
modules
#283
Conversation
body = mock.sentinel.body | ||
is_valid = 'mock_status' | ||
message = 'mock_message' | ||
mock_validate_connection.return_value = [is_valid, message] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a pair, not a list. Please assign (is_valid, message)
to this return_value. Also, is_valid
should be a bool
value.
@mock.patch.object(api.API, 'validate_connection') | ||
@mock.patch('coriolis.policies.endpoints.ENDPOINTS_POLICY_PREFIX', | ||
'mock_prefix') | ||
def test_validate_connection_exept_not_found( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fix typo: test_validate_connection_except_not_found
@mock.patch.object(api.API, 'validate_connection') | ||
@mock.patch('coriolis.policies.endpoints.ENDPOINTS_POLICY_PREFIX', | ||
'mock_prefix') | ||
def test_validate_connection_exept_invalid_parameter_value( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, fix exept
typo
self, | ||
mock_get_endpoint_destination_minion_pool_options, | ||
mock_destination_minion_pool_options_collection, | ||
mock_get_diagnostics_policy_label, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: please rename this to mock_decode_base64_param
or similar
mock_context = mock.Mock() | ||
mock_req.environ = {'coriolis.context': mock_context} | ||
body = mock.sentinel.body | ||
mock__validate_create_body.return_value = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a tuple, not a list. Please replace
result | ||
) | ||
|
||
if data['migration']['replica_id'] is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not repeat the original method's logic. It'd be helpful to add a "expected_api_method" and "validation_expected" keys alongside the migration
data (not inside it). Therefore, you can mock the api method accordinlgy:
# `pop()` will remove the key: value from data, so you can pass it along to `create`
expected_api_method = data.pop('expected_api_method')
validation_expected = data.pop('validation_expected', False)
# ...
with mock.patch.object(api.API, expected_api_method) as mock_api_method:
# ...
result = self.migrations.create(mock_req, data)
# ....
# we don't care about the call args that much here
if validation_expected:
mock__validate_migration_input.assert_called_once()
mock_api_method.assert_called_once()
mock_single.assert_called_with(mock_api_method.return_value)
mock_req = mock.Mock() | ||
mock_context = mock.Mock() | ||
mock_req.environ = {'coriolis.context': mock_context} | ||
mock_values = [(f'mock_value_{i}') for i in range(1, 15)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.. let's not do this please. If you REALLY want to check these, use mock sentinels instead. IMO you can skip these long checks, the only thing that really matters is that the right API method is called if 'replica_id' is in migration
or not. You can also check validate_user_scripts
and normalize_user_scripts
calls since you have to mock them.
67d7b5a
to
7b666f8
Compare
|
||
result = self.diag_api.index(mock_req) | ||
|
||
mock_get_diagnostics_policy_label.assert_called_with("get") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change all these assertions to assert_called_once_with
, since these only get called once (as they should in this, and most cases)
(mock_get_endpoint_instance. | ||
assert_called_once_with)( | ||
mock_context, endpoint_id, | ||
mock_decode_base64_param.return_value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please set side_effect
to mock_decode_base_64_param
, so you don't pass the same thing twice here:
mock_decode_base64_param.side_effect = [id, env]
# ...
mock_get_endpoint_instance.assert_called_once_with(
mock_context, endpoint_id, id, env)
|
||
def setUp(self): | ||
super( | ||
EndpointSourceOptionsControllerTestCase, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't format code like this if the character limit allows otherwise. This fits in the limit, please adopt this style, format only where necessary:
def setUp(self):
super(EndpointDestinationOptionsControllerTestCase, self).setUp()
self.endpoint_api = endpoint.EndpointDestinationOptionsController()
Please apply this treatment wherever you see fit
option_names=options) | ||
(mock_source_options_collection. | ||
assert_called_once_with)( | ||
mock_get_endpoint_source_options.return_value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also looks like unnecessary formatting. Please replace with something like this:
mock_get_endpoint_destination_options.assert_called_once_with(
mock_context, endpoint_id,
env=env,
option_names=options)
mock_destination_options_collection.assert_called_once_with(
mock_get_endpoint_destination_options.return_value)
Apply this also wherever you see fit.
} | ||
endpoint = testutils.get_wrapped_function( | ||
self.endpoint_api._validate_create_body)( | ||
self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please pass self.endpoint_api
here, as that's an object of the class. self
is a TestCase
object here
} | ||
endpoint = testutils.get_wrapped_function( | ||
self.endpoint_api._validate_update_body)( | ||
self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
} | ||
endpoint = testutils.get_wrapped_function( | ||
self.endpoint_api._validate_update_body)( | ||
self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
KeyError, | ||
testutils.get_wrapped_function( | ||
self.endpoint_api._validate_update_body), | ||
self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
@mock.patch('coriolis.api.v1.migrations.CONF') | ||
def test_show( | ||
self, | ||
mock_CONF, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: please rename this to mock_conf
mock__validate_migration_input.assert_called_with( | ||
mock_context, data) | ||
mock_api_method.assert_called_once() | ||
mock_single.assert_called_with(mock_api_method.return_value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is otherwise good so far, please add tests for the rest of the methods of coriolis.api.v1.migrations
a55dd79
to
23bf910
Compare
from unittest import mock | ||
|
||
from coriolis.api.v1 import endpoint_source_minion_pool_options \ | ||
as endpoint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import should be a single line please
super( | ||
EndpointSourceMinionPoolOptionsControllerTestCase, | ||
self | ||
).setUp() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also fits in a single line
super(EndpointSourceOptionsControllerTestCase, self).setUp() | ||
self.endpoint_api = endpoint.EndpointSourceOptionsController() | ||
|
||
@mock.patch('coriolis.policies.endpoints.ENDPOINTS_POLICY_PREFIX', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you mocked this? This is actually a constant value, it doesn't need mocking. Please remove this mock, and also remove it from the other places you patched this constant.
from coriolis.tests import test_base | ||
from coriolis.tests import testutils | ||
|
||
from webob import exc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import should be in the "third-party" group. Please move it above the coriolis
imports:
from unittest import mock
from webob import exc
from coriolis.api.v1 import endpoints
# ...
Also, please apply this to al the places you have this imported
super(EndpointControllerTestCase, self).setUp() | ||
self.endpoint_api = endpoints.EndpointController() | ||
|
||
@mock.patch.object(endpoint_policies, 'get_endpoints_policy_label') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method also just returns a string, nothing special that needs mocking. Please remove this mock and others like it.
'origin_minion_pool_id': 'mock_origin_minion_pool_id', | ||
'instance_osmorphing_minion_pool_mappings': { | ||
'mock_instance_1', 'mock_instance_2'}, | ||
'instances': {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to fail, yes, but not because you set replication_count
to 12, but because you didn't set the same instances
list as instance_osmorphing_minion_pool_mappings
. Please set instances
to [mock_instance_1', 'mock_instance_2']
include_task_info=False | ||
) | ||
|
||
@ddt.data( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use ddt.file_data
here, so you can neatly put your test data inside a yml
file
'mock_destination_minion_pool_id', | ||
'instance_osmorphing_minion_pool_mappings': { | ||
'mock_instance_1', 'mock_instance_2'}, | ||
'instances': {'mock_instance_1', 'mock_instance_2'}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To more accurately match the real-world data, please assign instance_osmorphing_minion_pool_mappings
a map, like this:
{'mock_instance_1': 'mock_pool', 'mock_instance_2': 'mock_pool'}
;
and instances
should be a list of instances:
['mock_instance_1', 'mock_instance_2']
data['migration']['instances'], | ||
) | ||
|
||
@ddt.data( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, please use a yml
file using ddt.file_data
0d09662
to
47a8267
Compare
|
||
|
||
class DiagnosticsControllerTestCase(test_base.CoriolisBaseTestCase): | ||
"Test suite for the Coriolis api v1.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please either remove this, or make sure this is a docstring, with a more suggestive string:
"Test suite for the Coriolis api v1.""" | |
"""Test suite for the Coriolis Diagnostics v1 API""" |
|
||
@mock.patch.object(api.API, 'get') | ||
@mock.patch.object(diagnostic_view, 'collection') | ||
@mock.patch.object(diagnostics, 'get_diagnostics_policy_label') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't mock this please. Instead I've asked you to mock context
, so you can check whether mock_context.can
is called with the expected policy tag, which in this case should be migration:diagnostics:get
super(MigrationActionsControllerTestCase, self).setUp() | ||
self.migration_actions = migration_actions.MigrationActionsController() | ||
|
||
@mock.patch.object(migration_policies, 'get_migrations_policy_label') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please stop mocking anything related to policy_label
.
mock_validate_network_map, | ||
mock_validate_target_environment, | ||
mock_validate_storage_mappings, | ||
migrations, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shadows from coriolis.api.v1 import migrations
from this file. Please rename it to somehing like config
56afda7
to
d8ebcef
Compare
|
||
|
||
class DiagnosticsControllerTestCase(test_base.CoriolisBaseTestCase): | ||
"Test suite for the Coriolis Diagnostics v1 API""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still not a docstring. A Python docstring is defined between 3 double quotes, like this: """ doc string messsage """
Please pay more attention on the changes I propose in comments:
"Test suite for the Coriolis Diagnostics v1 API""" | |
"""Test suite for the Coriolis Diagnostics v1 API""" |
class EndpointDestinationOptionsControllerTestCase( | ||
test_base.CoriolisBaseTestCase | ||
): | ||
"Test suite for the Coriolis Endpoint Destination Options v1 API""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turn it into a docstring:
"Test suite for the Coriolis Endpoint Destination Options v1 API""" | |
"""Test suite for the Coriolis Endpoint Destination Options v1 API""" |
fdd764c
to
dad61b4
Compare
@@ -0,0 +1,5 @@ | |||
- config: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This config
is practically empty. I think you could just pass the exception names directly:
- NotFound
- InvalidParameterValue
@mock.patch.object(minion_pool_view, 'single') | ||
@mock.patch.object(api.API, 'deallocate_minion_pool') | ||
@ddt.file_data('data/minion_pool_exceptions.yml') | ||
@ddt.unpack |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
b08fc28
to
1139e1a
Compare
- config: | ||
exception_raised: True | ||
pool_retention_strategy: null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can lose the config
, as it is empty, therefore irrelevant:
- config: | |
exception_raised: True | |
pool_retention_strategy: null | |
- exception_raised: True | |
pool_retention_strategy: null |
@ddt.file_data('data/minion_pool_retention_strategy.yml') | ||
def test__check_pool_retention_strategy( | ||
self, | ||
config, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this, as it is not used
- config: | ||
minimum_minions: 1 | ||
maximum_minions: 1 | ||
minion_max_idle_time: 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This in fact raises an exception, but you never call it to check. Please check explanation below
1139e1a
to
619b3ff
Compare
coriolis/tests/api/v1/*
aa5ca3e
to
04193c3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM so far. Please continue adding tests for the rest of V1 modules.
b7cba43
to
2629ce0
Compare
2629ce0
to
a2164d9
Compare
self.assertEqual( | ||
expected_result, | ||
result | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add test for format_keyerror_message
b3788f2
to
b4fcc68
Compare
b4fcc68
to
149774f
Compare
This PR add unit tests for Coriolis/api/v1/*.py