Add unit tests to increase coverage
This patch proposes adding several new unit tests in effort to increase the total unit test coverage. Additionally, the ./tempest/serial_tests/ directory is not included in coverage calculation. The reason being we don't want to test tests with unit tests, which becomes a bit of an overkill. Finally, there is an addition of a new option for the coverage program called --fail-under. It will result the program in failure if the coverage is under set percentage. Reason for this implementation is to encourage writing unit tests for new code. Change-Id: I804116413cd7d73cd7e5ae71409a8855ef937b88
This commit is contained in:
parent
702f0befce
commit
433dbdc4b9
@ -1,4 +1,4 @@
|
|||||||
[run]
|
[run]
|
||||||
branch = True
|
branch = True
|
||||||
source = tempest
|
source = tempest
|
||||||
omit = tempest/tests/*,tempest/scenario/test_*.py,tempest/api/*
|
omit = tempest/tests/*,tempest/scenario/test_*.py,tempest/api/*,tempest/serial_tests/*
|
||||||
|
@ -17,8 +17,9 @@ from unittest import mock
|
|||||||
|
|
||||||
from urllib import parse as urlparse
|
from urllib import parse as urlparse
|
||||||
|
|
||||||
|
|
||||||
from tempest.common import compute
|
from tempest.common import compute
|
||||||
|
from tempest import exceptions
|
||||||
|
from tempest.lib import exceptions as lib_exc
|
||||||
from tempest.tests import base
|
from tempest.tests import base
|
||||||
|
|
||||||
|
|
||||||
@ -28,6 +29,58 @@ class TestCompute(base.TestCase):
|
|||||||
self.client_sock = mock.Mock()
|
self.client_sock = mock.Mock()
|
||||||
self.url = urlparse.urlparse("http://www.fake.com:80")
|
self.url = urlparse.urlparse("http://www.fake.com:80")
|
||||||
|
|
||||||
|
@mock.patch('tempest.common.compute.' 'config.CONF.validation')
|
||||||
|
def test_get_server_ip_connect_method_floating(self, mock_conf):
|
||||||
|
fake_server = {'id': 'fake-uuid'}
|
||||||
|
fake_vr = {'floating_ip': {'ip': '10.10.10.1'}}
|
||||||
|
mock_conf.connect_method = 'floating'
|
||||||
|
|
||||||
|
fake_server_ip = compute.get_server_ip(fake_server, fake_vr)
|
||||||
|
self.assertEqual(fake_server_ip, '10.10.10.1')
|
||||||
|
|
||||||
|
# assert that InvalidParam is raised when validadation
|
||||||
|
# resources are not set
|
||||||
|
self.assertRaises(lib_exc.InvalidParam,
|
||||||
|
compute.get_server_ip,
|
||||||
|
fake_server)
|
||||||
|
|
||||||
|
@mock.patch('tempest.common.compute.' 'config.CONF.validation')
|
||||||
|
def test_get_server_ip_connect_method_fixed(self, mock_conf):
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'addresses': {
|
||||||
|
'private': [
|
||||||
|
{'addr': '192.168.0.3',
|
||||||
|
'version': 4}]}}
|
||||||
|
mock_conf.connect_method = 'fixed'
|
||||||
|
mock_conf.network_for_ssh = 'private'
|
||||||
|
mock_conf.ip_version_for_ssh = 4
|
||||||
|
|
||||||
|
fake_server_ip = compute.get_server_ip(fake_server)
|
||||||
|
self.assertEqual(fake_server_ip, '192.168.0.3')
|
||||||
|
|
||||||
|
fake_server_v6 = {'id': 'fake-uuid',
|
||||||
|
'addresses': {
|
||||||
|
'private': [
|
||||||
|
{'addr': '2345:0425:2CA1::0567:5673:23b5',
|
||||||
|
'version': 6}]}}
|
||||||
|
# assert when server is unreachable
|
||||||
|
self.assertRaises(exceptions.ServerUnreachable,
|
||||||
|
compute.get_server_ip,
|
||||||
|
fake_server_v6)
|
||||||
|
|
||||||
|
@mock.patch('tempest.common.compute.' 'config.CONF.validation')
|
||||||
|
def test_get_server_ip_invalid_config(self, mock_conf):
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'addresses': {
|
||||||
|
'private': [
|
||||||
|
{'addr': '192.168.0.3',
|
||||||
|
'version': 4}]}}
|
||||||
|
mock_conf.connect_method = 'fake-method'
|
||||||
|
# assert when the connection method is not correctly set
|
||||||
|
self.assertRaises(lib_exc.InvalidConfiguration,
|
||||||
|
compute.get_server_ip,
|
||||||
|
fake_server)
|
||||||
|
|
||||||
def test_rfp_frame_not_cached(self):
|
def test_rfp_frame_not_cached(self):
|
||||||
# rfp negotiation frame arrived separately after upgrade
|
# rfp negotiation frame arrived separately after upgrade
|
||||||
# response, so it's not cached.
|
# response, so it's not cached.
|
||||||
|
@ -27,6 +27,78 @@ from tempest.tests import base
|
|||||||
import tempest.tests.utils as utils
|
import tempest.tests.utils as utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestServerWaiters(base.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestServerWaiters, self).setUp()
|
||||||
|
self.client = mock.MagicMock()
|
||||||
|
self.client.build_timeout = 1
|
||||||
|
self.client.build_interval = 1
|
||||||
|
|
||||||
|
def test_wait_for_server_status(self):
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'status': 'ACTIVE'}
|
||||||
|
self.client.show_server.return_value = ({'server': fake_server})
|
||||||
|
start_time = int(time.time())
|
||||||
|
waiters.wait_for_server_status(
|
||||||
|
self.client, fake_server['id'], 'ACTIVE')
|
||||||
|
end_time = int(time.time())
|
||||||
|
# Ensure waiter returns before build_timeout
|
||||||
|
self.assertLess((end_time - start_time), 10)
|
||||||
|
|
||||||
|
def test_wait_for_server_status_build(self):
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'status': 'BUILD'}
|
||||||
|
self.client.show_server.return_value = ({'server': fake_server})
|
||||||
|
start_time = int(time.time())
|
||||||
|
waiters.wait_for_server_status(self.client, fake_server['id'], 'BUILD')
|
||||||
|
end_time = int(time.time())
|
||||||
|
# Ensure waiter returns before build_timeout
|
||||||
|
self.assertLess((end_time - start_time), 10)
|
||||||
|
|
||||||
|
def test_wait_for_server_status_timeout(self):
|
||||||
|
time_mock = self.patch('time.time')
|
||||||
|
time_mock.side_effect = utils.generate_timeout_series(1)
|
||||||
|
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'status': 'SAVING'}
|
||||||
|
self.client.show_server.return_value = ({'server': fake_server})
|
||||||
|
self.assertRaises(lib_exc.TimeoutException,
|
||||||
|
waiters.wait_for_server_status,
|
||||||
|
self.client, fake_server['id'], 'ACTIVE')
|
||||||
|
|
||||||
|
def test_wait_for_server_status_error_on_server_build(self):
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'status': 'ERROR'}
|
||||||
|
self.client.show_server.return_value = ({'server': fake_server})
|
||||||
|
self.assertRaises(exceptions.BuildErrorException,
|
||||||
|
waiters.wait_for_server_status,
|
||||||
|
self.client, fake_server['id'], 'ACTIVE')
|
||||||
|
|
||||||
|
def test_wait_for_server_termination(self):
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'status': 'ACTIVE'}
|
||||||
|
self.client.show_server.side_effect = lib_exc.NotFound
|
||||||
|
waiters.wait_for_server_termination(self.client, fake_server['id'])
|
||||||
|
|
||||||
|
def test_wait_for_server_termination_timeout(self):
|
||||||
|
time_mock = self.patch('time.time')
|
||||||
|
time_mock.side_effect = utils.generate_timeout_series(1)
|
||||||
|
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'status': 'ACTIVE'}
|
||||||
|
self.assertRaises(lib_exc.TimeoutException,
|
||||||
|
waiters.wait_for_server_termination,
|
||||||
|
self.client, fake_server['id'])
|
||||||
|
|
||||||
|
def test_wait_for_server_termination_error_status(self):
|
||||||
|
fake_server = {'id': 'fake-uuid',
|
||||||
|
'status': 'ERROR'}
|
||||||
|
self.client.show_server.return_value = ({'server': fake_server})
|
||||||
|
self.assertRaises(lib_exc.DeleteErrorException,
|
||||||
|
waiters.wait_for_server_termination,
|
||||||
|
self.client, fake_server['id'])
|
||||||
|
|
||||||
|
|
||||||
class TestImageWaiters(base.TestCase):
|
class TestImageWaiters(base.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestImageWaiters, self).setUp()
|
super(TestImageWaiters, self).setUp()
|
||||||
@ -145,6 +217,15 @@ class TestImageWaiters(base.TestCase):
|
|||||||
waiters.wait_for_image_copied_to_stores,
|
waiters.wait_for_image_copied_to_stores,
|
||||||
self.client, 'fake_image_id')
|
self.client, 'fake_image_id')
|
||||||
|
|
||||||
|
def test_wait_for_image_copied_to_stores_status_killed(self):
|
||||||
|
self.client.show_image.return_value = ({
|
||||||
|
'status': 'killed',
|
||||||
|
'os_glance_importing_to_stores': None,
|
||||||
|
'os_glance_failed_import': 'fake_os_glance_failed_import'})
|
||||||
|
self.assertRaises(exceptions.ImageKilledException,
|
||||||
|
waiters.wait_for_image_copied_to_stores,
|
||||||
|
self.client, 'fake_image_id')
|
||||||
|
|
||||||
def test_wait_for_image_tasks_status(self):
|
def test_wait_for_image_tasks_status(self):
|
||||||
self.client.show_image_tasks.return_value = ({
|
self.client.show_image_tasks.return_value = ({
|
||||||
'tasks': [{'status': 'success'}]})
|
'tasks': [{'status': 'success'}]})
|
||||||
@ -168,6 +249,28 @@ class TestImageWaiters(base.TestCase):
|
|||||||
waiters.wait_for_image_tasks_status,
|
waiters.wait_for_image_tasks_status,
|
||||||
self.client, 'fake_image_id', 'success')
|
self.client, 'fake_image_id', 'success')
|
||||||
|
|
||||||
|
def test_wait_for_tasks_status(self):
|
||||||
|
self.client.show_tasks.return_value = ({
|
||||||
|
'status': 'success'})
|
||||||
|
start_time = int(time.time())
|
||||||
|
waiters.wait_for_tasks_status(
|
||||||
|
self.client, 'fake_task_id', 'success')
|
||||||
|
end_time = int(time.time())
|
||||||
|
# Ensure waiter returns before build_timeout
|
||||||
|
self.assertLess((end_time - start_time), 10)
|
||||||
|
|
||||||
|
def test_wait_for_tasks_status_timeout(self):
|
||||||
|
time_mock = self.patch('time.time')
|
||||||
|
self.patch('time.time', side_effect=[0., 1.])
|
||||||
|
time_mock.side_effect = utils.generate_timeout_series(1)
|
||||||
|
|
||||||
|
self.client.show_tasks.return_value = (
|
||||||
|
{'status': 'success'},
|
||||||
|
{'status': 'processing'})
|
||||||
|
self.assertRaises(lib_exc.TimeoutException,
|
||||||
|
waiters.wait_for_tasks_status,
|
||||||
|
self.client, 'fake_task_id', 'success')
|
||||||
|
|
||||||
|
|
||||||
class TestInterfaceWaiters(base.TestCase):
|
class TestInterfaceWaiters(base.TestCase):
|
||||||
|
|
||||||
@ -366,6 +469,31 @@ class TestVolumeWaiters(base.TestCase):
|
|||||||
mock.call(mock.sentinel.volume_id),
|
mock.call(mock.sentinel.volume_id),
|
||||||
mock.call(mock.sentinel.volume_id)])
|
mock.call(mock.sentinel.volume_id)])
|
||||||
|
|
||||||
|
def test_wait_for_volume_retype(self):
|
||||||
|
fake_volume = {'volume_type': {'id': 'fake-uuid'}}
|
||||||
|
show_volume = mock.Mock(return_value={'volume': fake_volume})
|
||||||
|
client = mock.Mock(resource_type="volume",
|
||||||
|
build_interval=1,
|
||||||
|
build_timeout=1,
|
||||||
|
show_volume=show_volume)
|
||||||
|
waiters.wait_for_volume_retype(
|
||||||
|
client, mock.sentinel.volume_id, fake_volume['volume_type'])
|
||||||
|
|
||||||
|
def test_wait_for_volume_retype_timeout(self):
|
||||||
|
fake_volume = {'volume_type': {'id': 'fake-uuid'}}
|
||||||
|
show_volume = mock.Mock(return_value={'volume': fake_volume})
|
||||||
|
client = mock.Mock(resource_type="volume",
|
||||||
|
build_interval=1,
|
||||||
|
build_timeout=1,
|
||||||
|
show_volume=show_volume)
|
||||||
|
|
||||||
|
self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
|
||||||
|
self.patch('time.sleep')
|
||||||
|
self.assertRaises(lib_exc.TimeoutException,
|
||||||
|
waiters.wait_for_volume_retype,
|
||||||
|
client, mock.sentinel.volume_id,
|
||||||
|
'fake_volume_type')
|
||||||
|
|
||||||
@mock.patch.object(time, 'sleep')
|
@mock.patch.object(time, 'sleep')
|
||||||
def test_wait_for_volume_status_error_restoring(self, mock_sleep):
|
def test_wait_for_volume_status_error_restoring(self, mock_sleep):
|
||||||
# Tests that the wait method raises VolumeRestoreErrorException if
|
# Tests that the wait method raises VolumeRestoreErrorException if
|
||||||
@ -450,7 +578,25 @@ class TestVolumeWaiters(base.TestCase):
|
|||||||
mock.call(uuids.volume_id),
|
mock.call(uuids.volume_id),
|
||||||
mock.call(uuids.volume_id)])
|
mock.call(uuids.volume_id)])
|
||||||
|
|
||||||
def test_wait_for_volume_attachment(self):
|
def test_wait_for_volume_attachment_create_timeout(self):
|
||||||
|
show_volume = mock.MagicMock(return_value={
|
||||||
|
'volume': {'attachments': [
|
||||||
|
{'attachment_id': uuids.attachment_id,
|
||||||
|
'server_id': uuids.server_id,
|
||||||
|
'volume_id': uuids.volume_id}]}})
|
||||||
|
client = mock.Mock(spec=volumes_client.VolumesClient,
|
||||||
|
build_interval=1,
|
||||||
|
build_timeout=1,
|
||||||
|
show_volume=show_volume)
|
||||||
|
self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
|
||||||
|
self.patch('time.sleep')
|
||||||
|
# Assert that a timeout is raised if the attachment is not
|
||||||
|
# created within required time
|
||||||
|
self.assertRaises(lib_exc.TimeoutException,
|
||||||
|
waiters.wait_for_volume_attachment_create,
|
||||||
|
client, 'fake_volume_id', 'fake_server_id')
|
||||||
|
|
||||||
|
def test_wait_for_volume_attachment_remove(self):
|
||||||
vol_detached = {'volume': {'attachments': []}}
|
vol_detached = {'volume': {'attachments': []}}
|
||||||
vol_attached = {'volume': {'attachments': [
|
vol_attached = {'volume': {'attachments': [
|
||||||
{'attachment_id': uuids.attachment_id}]}}
|
{'attachment_id': uuids.attachment_id}]}}
|
||||||
@ -469,7 +615,7 @@ class TestVolumeWaiters(base.TestCase):
|
|||||||
mock.call(uuids.volume_id),
|
mock.call(uuids.volume_id),
|
||||||
mock.call(uuids.volume_id)])
|
mock.call(uuids.volume_id)])
|
||||||
|
|
||||||
def test_wait_for_volume_attachment_timeout(self):
|
def test_wait_for_volume_attachment_remove_timeout(self):
|
||||||
show_volume = mock.MagicMock(return_value={
|
show_volume = mock.MagicMock(return_value={
|
||||||
'volume': {'attachments': [
|
'volume': {'attachments': [
|
||||||
{'attachment_id': uuids.attachment_id}]}})
|
{'attachment_id': uuids.attachment_id}]}})
|
||||||
@ -635,6 +781,67 @@ class TestVolumeWaiters(base.TestCase):
|
|||||||
.1
|
.1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_wait_for_caching(self):
|
||||||
|
mock_client = mock.Mock(
|
||||||
|
build_interval=1,
|
||||||
|
build_timeout=1
|
||||||
|
)
|
||||||
|
mock_cache_client = mock.Mock()
|
||||||
|
mock_cache_client.list_cache.return_value = {
|
||||||
|
"cached_images": [{
|
||||||
|
"image_id": 'fake_image_id'}]}
|
||||||
|
waiters.wait_for_caching(
|
||||||
|
mock_client, mock_cache_client, 'fake_image_id')
|
||||||
|
|
||||||
|
def test_wait_for_caching_timeout(self):
|
||||||
|
time_mock = self.patch('time.time')
|
||||||
|
time_mock.side_effect = utils.generate_timeout_series(1)
|
||||||
|
|
||||||
|
mock_client = mock.Mock(
|
||||||
|
build_interval=1,
|
||||||
|
build_timeout=1
|
||||||
|
)
|
||||||
|
mock_cache_client = mock.Mock()
|
||||||
|
mock_cache_client.list_cache.return_value = {
|
||||||
|
"cached_images": [{
|
||||||
|
"image_id": 'fake_image_id'}]}
|
||||||
|
# Assert that TimeoutException is raised when the image
|
||||||
|
# failed to cache in time
|
||||||
|
self.assertRaises(
|
||||||
|
lib_exc.TimeoutException,
|
||||||
|
waiters.wait_for_caching,
|
||||||
|
mock_client,
|
||||||
|
mock_cache_client,
|
||||||
|
'fake_image_id'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_wait_for_object_create(self):
|
||||||
|
mock_object_client = mock.Mock(
|
||||||
|
build_interval=1,
|
||||||
|
build_timeout=1
|
||||||
|
)
|
||||||
|
waiters.wait_for_object_create(
|
||||||
|
mock_object_client, 'fake_container', 'fake_object')
|
||||||
|
|
||||||
|
def test_wait_for_object_create_timeout(self):
|
||||||
|
time_mock = self.patch('time.time')
|
||||||
|
time_mock.side_effect = utils.generate_timeout_series(1)
|
||||||
|
|
||||||
|
mock_object_client = mock.Mock(
|
||||||
|
build_interval=1,
|
||||||
|
build_timeout=1
|
||||||
|
)
|
||||||
|
# Assert that TimeoutException is raised when the object is not
|
||||||
|
# created in time
|
||||||
|
self.assertRaises(
|
||||||
|
lib_exc.TimeoutException,
|
||||||
|
waiters.wait_for_object_create,
|
||||||
|
mock_object_client,
|
||||||
|
'fake_container',
|
||||||
|
'fake_object',
|
||||||
|
.1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPortCreationWaiter(base.TestCase):
|
class TestPortCreationWaiter(base.TestCase):
|
||||||
def test_wait_for_port_status(self):
|
def test_wait_for_port_status(self):
|
||||||
|
@ -38,6 +38,13 @@ class TestCredClientV2(base.TestCase):
|
|||||||
self.projects_client.create_tenant.assert_called_once_with(
|
self.projects_client.create_tenant.assert_called_once_with(
|
||||||
name='fake_name', description='desc')
|
name='fake_name', description='desc')
|
||||||
|
|
||||||
|
def test_show_project(self):
|
||||||
|
self.projects_client.show_tenant.return_value = {
|
||||||
|
'tenant': 'a_tenant'
|
||||||
|
}
|
||||||
|
res = self.creds_client.show_project('fake_id')
|
||||||
|
self.assertEqual('a_tenant', res)
|
||||||
|
|
||||||
def test_delete_project(self):
|
def test_delete_project(self):
|
||||||
self.creds_client.delete_project('fake_id')
|
self.creds_client.delete_project('fake_id')
|
||||||
self.projects_client.delete_tenant.assert_called_once_with(
|
self.projects_client.delete_tenant.assert_called_once_with(
|
||||||
@ -79,11 +86,32 @@ class TestCredClientV3(base.TestCase):
|
|||||||
self.projects_client.create_project.assert_called_once_with(
|
self.projects_client.create_project.assert_called_once_with(
|
||||||
name='fake_name', description='desc', domain_id='fake_domain_id')
|
name='fake_name', description='desc', domain_id='fake_domain_id')
|
||||||
|
|
||||||
|
def test_show_project(self):
|
||||||
|
self.projects_client.show_project.return_value = {
|
||||||
|
'project': 'a_tenant'
|
||||||
|
}
|
||||||
|
res = self.creds_client.show_project('fake_id')
|
||||||
|
self.assertEqual('a_tenant', res)
|
||||||
|
|
||||||
def test_delete_project(self):
|
def test_delete_project(self):
|
||||||
self.creds_client.delete_project('fake_id')
|
self.creds_client.delete_project('fake_id')
|
||||||
self.projects_client.delete_project.assert_called_once_with(
|
self.projects_client.delete_project.assert_called_once_with(
|
||||||
'fake_id')
|
'fake_id')
|
||||||
|
|
||||||
|
def test_create_domain(self):
|
||||||
|
self.domains_client.create_domain.return_value = {
|
||||||
|
'domain': 'a_tenant'
|
||||||
|
}
|
||||||
|
res = self.creds_client.create_domain('fake_name', 'desc')
|
||||||
|
self.assertEqual('a_tenant', res)
|
||||||
|
self.domains_client.create_domain.assert_called_once_with(
|
||||||
|
name='fake_name', description='desc')
|
||||||
|
|
||||||
|
def test_delete_domain(self):
|
||||||
|
self.creds_client.delete_domain('fake_id')
|
||||||
|
self.domains_client.delete_domain.assert_called_once_with(
|
||||||
|
'fake_id')
|
||||||
|
|
||||||
def test_get_credentials(self):
|
def test_get_credentials(self):
|
||||||
ret = self.creds_client.get_credentials(
|
ret = self.creds_client.get_credentials(
|
||||||
{'name': 'some_user', 'id': 'fake_id'},
|
{'name': 'some_user', 'id': 'fake_id'},
|
||||||
|
2
tox.ini
2
tox.ini
@ -64,7 +64,7 @@ commands =
|
|||||||
coverage combine
|
coverage combine
|
||||||
coverage html -d cover
|
coverage html -d cover
|
||||||
coverage xml -o cover/coverage.xml
|
coverage xml -o cover/coverage.xml
|
||||||
coverage report
|
coverage report -m --fail-under=76
|
||||||
|
|
||||||
[testenv:debug]
|
[testenv:debug]
|
||||||
commands = oslo_debug_helper -t tempest/tests {posargs}
|
commands = oslo_debug_helper -t tempest/tests {posargs}
|
||||||
|
Loading…
Reference in New Issue
Block a user