Add unit tests for untested code

Add unit tests and '# pragma: no cover'
for exclude some code that doesn't require test.

Change-Id: Ib071208bd38c7b1102aa341be0d6bf803b647596
This commit is contained in:
Vladislav Kuzmin 2015-03-12 10:36:28 +03:00
parent 7fb06e8317
commit 49f1efc773
9 changed files with 385 additions and 15 deletions

View File

@ -23,7 +23,6 @@ from oslo_config import cfg
from oslo_log import log
from oslo_log import loggers
import pecan
from pecan import hooks
import webob
LOG = log.getLogger(__name__)
@ -71,7 +70,7 @@ CONF.register_opts(API_OPTS, opt_group)
log.register_options(CONF)
class JSONErrorHook(hooks.PecanHook):
class JSONErrorHook(pecan.hooks.PecanHook):
"""
A pecan hook that translates webob HTTP errors into a JSON format.
"""
@ -134,7 +133,7 @@ def setup_app(config):
debug=CONF.api.app_dev_mode,
static_root=static_root,
template_path=template_path,
hooks=[JSONErrorHook(), hooks.RequestViewerHook(
hooks=[JSONErrorHook(), pecan.hooks.RequestViewerHook(
{'items': ['status', 'method', 'controller', 'path', 'body']},
headers=False, writer=loggers.WritableLogger(LOG, logging.DEBUG)
)]

View File

@ -37,11 +37,11 @@ class RestControllerWithValidation(rest.RestController):
def __init__(self, validator):
self.validator = validator
def get_item(self, item_id):
def get_item(self, item_id): # pragma: no cover
"""Handler for getting item"""
raise NotImplemented
def store_item(self, item_in_json):
def store_item(self, item_in_json): # pragma: no cover
"""Handler for storing item. Should return new item id"""
raise NotImplemented

View File

@ -32,11 +32,11 @@ class PluggableBackend(object):
def __get_backend(self):
if not self.__backend:
backend_name = CONF[self.__pivot]
if backend_name not in self.__backends:
if backend_name not in self.__backends: # pragma: no cover
raise Exception('Invalid backend: %s' % backend_name)
backend = self.__backends[backend_name]
if isinstance(backend, tuple):
if isinstance(backend, tuple): # pragma: no cover
name = backend[0]
fromlist = backend[1]
else:

View File

@ -0,0 +1,159 @@
# Copyright (c) 2015 Mirantis, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Tests for API's controllers"""
import mock
from oslotest import base
from refstack.api.controllers import root
from refstack.api.controllers import v1
class RootControllerTestCase(base.BaseTestCase):
def test_index(self):
controller = root.RootController()
result = controller.index()
self.assertEqual(result, {'Root': 'OK'})
class ResultsControllerTestCase(base.BaseTestCase):
def setUp(self):
super(ResultsControllerTestCase, self).setUp()
self.validator = mock.Mock()
self.controller = v1.ResultsController(self.validator)
@mock.patch('refstack.db.get_test')
@mock.patch('refstack.db.get_test_results')
def test_get(self, mock_get_test_res, mock_get_test):
self.validator.assert_id.return_value = True
test_info = mock.Mock()
test_info.cpid = 'foo'
test_info.created_at = 'bar'
test_info.duration_seconds = 999
mock_get_test.return_value = test_info
mock_get_test_res.return_value = [('test1',), ('test2',), ('test3',)]
actual_result = self.controller.get_one('fake_arg')
expected_result = {
'cpid': 'foo',
'created_at': 'bar',
'duration_seconds': 999,
'results': ['test1', 'test2', 'test3']
}
self.assertEqual(actual_result, expected_result)
mock_get_test_res.assert_called_once_with('fake_arg')
mock_get_test.assert_called_once_with('fake_arg')
self.validator.assert_id.assert_called_once_with('fake_arg')
@mock.patch('refstack.db.store_results')
@mock.patch('pecan.response')
@mock.patch('refstack.common.validators.safe_load_json_body')
def test_post(self, mock_safe_load, mock_response, mock_store_results):
mock_safe_load.return_value = 'fake_item'
mock_store_results.return_value = 'fake_test_id'
result = self.controller.post()
self.assertEqual(result, {'test_id': 'fake_test_id'})
self.assertEqual(mock_response.status, 201)
mock_safe_load.assert_called_once_with(self.validator)
mock_store_results.assert_called_once_with('fake_item')
@mock.patch('pecan.abort')
@mock.patch('refstack.db.get_test')
def test_get_item_failed(self, mock_get_test, mock_abort):
mock_get_test.return_value = None
mock_abort.side_effect = Exception()
self.assertRaises(Exception,
self.controller.get_item,
'fake_id')
@mock.patch('refstack.db.get_test')
@mock.patch('refstack.db.get_test_results')
def test_get_item(self, mock_get_test_res, mock_get_test):
test_info = mock.Mock()
test_info.cpid = 'foo'
test_info.created_at = 'bar'
test_info.duration_seconds = 999
mock_get_test.return_value = test_info
mock_get_test_res.return_value = [('test1',), ('test2',), ('test3',)]
actual_result = self.controller.get_item('fake_id')
expected_result = {
'cpid': 'foo',
'created_at': 'bar',
'duration_seconds': 999,
'results': ['test1', 'test2', 'test3']
}
self.assertEqual(actual_result, expected_result)
mock_get_test_res.assert_called_once_with('fake_id')
mock_get_test.assert_called_once_with('fake_id')
@mock.patch('refstack.db.store_results')
def test_store_item(self, mock_store_item):
mock_store_item.return_value = 'fake_result'
result = self.controller.store_item('fake_item')
self.assertEqual(result, {'test_id': 'fake_result'})
mock_store_item.assert_called_once_with('fake_item')
class RestControllerWithValidationTestCase(base.BaseTestCase):
def setUp(self):
super(RestControllerWithValidationTestCase, self).setUp()
self.validator = mock.Mock()
self.controller = v1.RestControllerWithValidation(self.validator)
@mock.patch('pecan.response')
@mock.patch('refstack.common.validators.safe_load_json_body')
def test_post(self, mock_safe_load, mock_response):
mock_safe_load.return_value = 'fake_item'
self.controller.store_item = mock.Mock(return_value='fake_id')
result = self.controller.post()
self.assertEqual(result, 'fake_id')
self.assertEqual(mock_response.status, 201)
mock_safe_load.assert_called_once_with(self.validator)
self.controller.store_item.assert_called_once_with('fake_item')
def test_get_one_return_item(self):
self.validator.assert_id.return_value = True
self.controller.get_item = mock.Mock(return_value='fake_item')
result = self.controller.get_one('fake_arg')
self.assertEqual(result, 'fake_item')
self.validator.assert_id.assert_called_once_with('fake_arg')
self.controller.get_item.assert_called_once_with(item_id='fake_arg')
def test_get_one_return_schema(self):
self.validator.assert_id.return_value = False
self.validator.schema = 'fake_schema'
result = self.controller.get_one('schema')
self.assertEqual(result, 'fake_schema')
@mock.patch('pecan.abort')
def test_get_one_aborut(self, mock_abort):
self.validator.assert_id.return_value = False
self.controller.get_one('fake_arg')
mock_abort.assert_called_once_with(404)

View File

@ -0,0 +1,163 @@
# Copyright (c) 2015 Mirantis, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Tests for API's utility"""
import json
import mock
from oslo_config import fixture as config_fixture
from oslotest import base
import webob
from refstack.api import app
class JSONErrorHookTestCase(base.BaseTestCase):
def setUp(self):
super(JSONErrorHookTestCase, self).setUp()
self.config_fixture = config_fixture.Config()
self.CONF = self.useFixture(self.config_fixture).conf
def test_on_error_with_webob_instance(self):
self.CONF.set_override('app_dev_mode',
False,
'api')
exc = mock.Mock(spec=webob.exc.HTTPError)
exc.status_int = 999
exc.status = 111
exc.title = 'fake_title'
with mock.patch.object(webob, 'Response') as response:
response.return_value = 'fake_value'
hook = app.JSONErrorHook()
result = hook.on_error(mock.Mock(), exc)
self.assertEqual(result, 'fake_value')
body = {'code': exc.status_int, 'title': exc.title}
response.assert_called_once_with(body=json.dumps(body),
status=exc.status,
content_type='application/json')
def test_on_error_with_webob_instance_with_debug(self):
self.CONF.set_override('app_dev_mode',
True,
'api')
exc = mock.Mock(spec=webob.exc.HTTPError)
exc.status_int = 999
exc.status = 111
exc.title = 'fake_title'
with mock.patch.object(webob, 'Response') as response:
response.return_value = 'fake_value'
hook = app.JSONErrorHook()
result = hook.on_error(mock.Mock(), exc)
self.assertEqual(result, 'fake_value')
body = {
'code': exc.status_int,
'title': exc.title,
'detail': str(exc)
}
response.assert_called_once_with(body=json.dumps(body),
status=exc.status,
content_type='application/json')
@mock.patch.object(webob, 'Response')
def test_on_error_not_webob_instance(self, response):
self.CONF.set_override('app_dev_mode',
False,
'api')
response.return_value = 'fake_value'
exc = mock.Mock()
hook = app.JSONErrorHook()
result = hook.on_error(mock.Mock(), exc)
self.assertEqual(result, 'fake_value')
body = {'code': 500, 'title': 'Internal Server Error'}
response.assert_called_once_with(body=json.dumps(body),
status=500,
content_type='application/json')
@mock.patch.object(webob, 'Response')
def test_on_error_not_webob_instance_with_debug(self, response):
self.CONF.set_override('app_dev_mode',
True,
'api')
response.return_value = 'fake_value'
exc = mock.Mock()
hook = app.JSONErrorHook()
result = hook.on_error(mock.Mock(), exc)
self.assertEqual(result, 'fake_value')
body = {
'code': 500,
'title': 'Internal Server Error',
'detail': str(exc)
}
response.assert_called_once_with(body=json.dumps(body),
status=500,
content_type='application/json')
class SetupAppTestCase(base.BaseTestCase):
def setUp(self):
super(SetupAppTestCase, self).setUp()
self.config_fixture = config_fixture.Config()
self.CONF = self.useFixture(self.config_fixture).conf
@mock.patch('pecan.hooks')
@mock.patch.object(app, 'JSONErrorHook')
@mock.patch('os.path.join')
@mock.patch('pecan.make_app')
def test_setup_app(self, make_app, os_join,
json_error_hook, pecan_hooks):
self.CONF.set_override('app_dev_mode',
True,
'api')
self.CONF.set_override('template_path',
'fake_template_path',
'api')
self.CONF.set_override('static_root',
'fake_static_root',
'api')
os_join.return_value = 'fake_project_root'
json_error_hook.return_value = 'json_error_hook'
pecan_hooks.RequestViewerHook.return_value = 'request_viewer_hook'
pecan_config = mock.Mock()
pecan_config.app = {'root': 'fake_pecan_config'}
make_app.return_value = 'fake_app'
result = app.setup_app(pecan_config)
self.assertEqual(result, 'fake_app')
app_conf = dict(pecan_config.app)
make_app.assert_called_once_with(
app_conf.pop('root'),
debug=True,
static_root='fake_static_root',
template_path='fake_template_path',
hooks=['json_error_hook', 'request_viewer_hook']
)

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
"""Tests for database API."""
"""Tests for database."""
import six
import mock
@ -21,6 +21,26 @@ from oslotest import base
from refstack import db
from refstack.db.sqlalchemy import api
from refstack.db.sqlalchemy import models
class RefStackBaseTestCase(base.BaseTestCase):
"""Test case for RefStackBase model."""
@mock.patch('oslo_utils.timeutils.utcnow')
def test_delete(self, utcnow):
utcnow.return_value = '123'
base_model = models.RefStackBase()
base_model.id = 'fake_id'
base_model.save = mock.Mock()
session = mock.MagicMock()
base_model.delete(session)
self.assertEqual(base_model.deleted, 'fake_id')
self.assertEqual(base_model.deleted_at, '123')
base_model.save.assert_called_once_with(session=session)
class DBAPITestCase(base.BaseTestCase):
@ -67,6 +87,12 @@ class DBHelpersTestCase(base.BaseTestCase):
facade.get_session.assert_called_once_with(**fake_kwargs)
self.assertEqual(result, 'fake_session')
@mock.patch('oslo_db.sqlalchemy.session.EngineFacade.from_config')
def test_create_facade_lazily(self, session):
session.return_value = 'fake_session'
result = api._create_facade_lazily()
self.assertEqual(result, 'fake_session')
class DBBackendTestCase(base.BaseTestCase):
"""Test case for database backend."""

View File

@ -20,6 +20,19 @@ import mock
from oslotest import base
from refstack.db import migration
from refstack.db.migrations.alembic import migration as alembic_migration
class AlembicConfigTestCase(base.BaseTestCase):
@mock.patch('alembic.config.Config')
@mock.patch('os.path.join')
def test_alembic_config(self, os_join, alembic_config):
os_join.return_value = 'fake_path'
alembic_config.return_value = 'fake_config'
result = alembic_migration._alembic_config()
self.assertEqual(result, 'fake_config')
alembic_config.assert_called_once_with('fake_path')
class MigrationTestCase(base.BaseTestCase):

View File

@ -33,6 +33,13 @@ class ValidatorsTestCase(base.BaseTestCase):
def test_is_uuid_fail(self):
self.assertFalse(validators.is_uuid('some_string'))
def test_checker_uuid(self):
value = validators.checker_uuid('12345678123456781234567812345678')
self.assertTrue(value)
def test_checker_uuid_fail(self):
self.assertFalse(validators.checker_uuid('some_string'))
class TestResultValidatorTestCase(base.BaseTestCase):
"""Test case for database TestResultValidator."""
@ -50,6 +57,13 @@ class TestResultValidatorTestCase(base.BaseTestCase):
super(TestResultValidatorTestCase, self).setUp()
self.validator = validators.TestResultValidator()
def test_assert_id(self):
value = self.validator.assert_id('12345678123456781234567812345678')
self.assertTrue(value)
def test_assert_id_fail(self):
self.assertFalse(self.validator.assert_id('some_string'))
def test_validation(self):
with mock.patch('jsonschema.validate') as mock_validate:
self.validator.validate(self.FAKE_TESTS_RESULTS_JSON)
@ -64,12 +78,6 @@ class TestResultValidatorTestCase(base.BaseTestCase):
self.validator.validate,
wrong_tests_result)
def test_assert_id(self):
self.assertTrue(validators.is_uuid('12345678123456781234567812345678'))
def test_assert_id_fail(self):
self.assertFalse(validators.is_uuid('some_string'))
@mock.patch('pecan.request')
def test_safe_load_json_body(self, mock_request):
mock_request.body = self.FAKE_TESTS_RESULTS_JSON

View File

@ -44,7 +44,9 @@ commands =
commands = {posargs}
[testenv:py27-cover]
commands = python setup.py testr --coverage --omit='*/tests*' --testr-args='{posargs}'
commands = python setup.py testr --coverage \
--omit='{toxinidir}/refstack/tests*,{toxinidir}/refstack/api/config.py,{toxinidir}/refstack/db/migrations/alembic/env.py,{toxinidir}/refstack/opts.py' \
--testr-args='{posargs}'
[tox:jenkins]
downloadcache = ~/cache/pip