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:
Katarina Strenkova 2023-08-29 15:17:57 +00:00
parent 702f0befce
commit 433dbdc4b9
5 changed files with 293 additions and 5 deletions

View File

@ -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/*

View File

@ -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.

View File

@ -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):

View File

@ -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'},

View File

@ -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}