Merge pull request #5 from gnuoy/feature/unit-tests

Add unit_tests and drive by assorted
This commit is contained in:
Frode Nordahl 2019-01-16 15:57:39 +01:00 committed by GitHub
commit d00160a97c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 199 additions and 5 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.tox
.testrepository
.unit-state.db
.stestr/
__pycache__/

8
.testr.conf Normal file
View File

@ -0,0 +1,8 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ ./unit_tests $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

6
.travis.yml Normal file
View File

@ -0,0 +1,6 @@
sudo: false
language: python
python:
- "3.4"
install: pip install tox-travis
script: tox -e pep8,py3

View File

@ -1,4 +1,13 @@
name: cinder-backend
summary: OpenStack Cinder backend interface
version: 1
repo: https://github.com/mskalka/interface-cinder-backend
repo: https://github.com/openstack-charmers/interface-cinder-backend
ignore:
- 'unit_tests'
- 'Makefile'
- '.testr.conf'
- 'test-requirements.txt'
- 'tox.ini'
- '.gitignore'
- '.gitreview'
- '.unit-state.db'

View File

@ -15,15 +15,15 @@ class CinderBackendProvides(RelationBase):
def cinder_backend_joined(self):
conv = self.conversation()
conv.set_state('{relation_name}.joined')
self.set_state('{relation_name}.connected')
self.set_state('{relation_name}.available')
conv.set_state('{relation_name}.connected')
conv.set_state('{relation_name}.available')
@hook('{provides:cinder-backend}-relation-{broken, departed}')
def cinder_backend_departed(self):
conv = self.conversation()
conv.remove_state('{relation_name}.joined')
self.remove_state('{relation_name}.available')
self.remove_state('{relation_name}.connected')
conv.remove_state('{relation_name}.available')
conv.remove_state('{relation_name}.connected')
conv.set_state('{relation_name}.departing')
def configure_principal(self, backend_name, configuration, stateless=None):

6
test-requirements.txt Normal file
View File

@ -0,0 +1,6 @@
# Lint and unit test requirements
flake8
os-testr>=0.4.1
charms.reactive
mock>=1.2
coverage>=3.6

28
tox.ini Normal file
View File

@ -0,0 +1,28 @@
[tox]
skipsdist = True
envlist = pep8,py3
skip_missing_interpreters = True
[testenv]
setenv = VIRTUAL_ENV={envdir}
PYTHONHASHSEED=0
TERM=linux
install_command =
pip install {opts} {packages}
[testenv:py3]
basepython = python3
deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs}
[testenv:pep8]
basepython = python3
deps = -r{toxinidir}/test-requirements.txt
commands = flake8 {posargs} .
[testenv:venv]
commands = {posargs}
[flake8]
# E402 ignore necessary for path append before sys module import in actions
ignore = E402

0
unit_tests/__init__.py Normal file
View File

132
unit_tests/test_provides.py Normal file
View File

@ -0,0 +1,132 @@
import unittest
import mock
with mock.patch('charmhelpers.core.hookenv.metadata') as _meta:
_meta.return_Value = 'ss'
import provides
_hook_args = {}
TO_PATCH = [
]
def mock_hook(*args, **kwargs):
def inner(f):
# remember what we were passed. Note that we can't actually determine
# the class we're attached to, as the decorator only gets the function.
_hook_args[f.__name__] = dict(args=args, kwargs=kwargs)
return f
return inner
class _unit_mock:
def __init__(self, unit_name, received=None):
self.unit_name = unit_name
self.received = received or {}
class _relation_mock:
def __init__(self, application_name=None, units=None):
self.to_publish_raw = {}
self.application_name = application_name
self.units = units
class TestCinderBackendProvides(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._patched_hook = mock.patch('charms.reactive.when', mock_hook)
cls._patched_hook_started = cls._patched_hook.start()
# force provides to rerun the mock_hook decorator:
# try except is Python2/Python3 compatibility as Python3 has moved
# reload to importlib.
try:
reload(provides)
except NameError:
import importlib
importlib.reload(provides)
@classmethod
def tearDownClass(cls):
cls._patched_hook.stop()
cls._patched_hook_started = None
cls._patched_hook = None
# and fix any breakage we did to the module
try:
reload(provides)
except NameError:
import importlib
importlib.reload(provides)
def patch(self, method):
_m = mock.patch.object(self.obj, method)
_mock = _m.start()
self.addCleanup(_m.stop)
return _mock
def setUp(self):
self.relation_obj = provides.CinderBackendProvides(
'some-relation',
[])
self._patches = {}
self._patches_start = {}
self.obj = provides
for method in TO_PATCH:
setattr(self, method, self.patch(method))
def tearDown(self):
self.relation_obj = None
for k, v in self._patches.items():
v.stop()
setattr(self, k, None)
self._patches = None
self._patches_start = None
def patch_relation_obj(self, attr, return_value=None):
mocked = mock.patch.object(self.relation_obj, attr)
self._patches[attr] = mocked
started = mocked.start()
started.return_value = return_value
self._patches_start[attr] = started
setattr(self, attr, started)
def test_cinder_backend_joined(self):
mock_conv = mock.MagicMock()
self.patch_relation_obj('conversation', mock_conv)
self.relation_obj.cinder_backend_joined()
expected_calls = [
mock.call('{relation_name}.joined'),
mock.call('{relation_name}.connected'),
mock.call('{relation_name}.available')]
mock_conv.set_state.assert_has_calls(expected_calls)
def test_cinder_backend_departed(self):
mock_conv = mock.MagicMock()
self.patch_relation_obj('conversation', mock_conv)
self.relation_obj.cinder_backend_departed()
expected_calls = [
mock.call('{relation_name}.joined'),
mock.call('{relation_name}.available'),
mock.call('{relation_name}.connected')]
mock_conv.remove_state.assert_has_calls(expected_calls)
mock_conv.set_state.assert_called_once_with(
'{relation_name}.departing')
def test_configure_principal(self):
mock_conv = mock.MagicMock()
self.patch_relation_obj('conversation', mock_conv)
self.relation_obj.configure_principal(
'cinder-supernas',
[('cinder', 'ss')],
True)
expect = ('{"cinder": {"/etc/cinder/cinder.conf": {"sections": '
'{"cinder-supernas": [["cinder", "ss"]]}}}}')
mock_conv.set_remote.assert_called_once_with(
backend_name='cinder-supernas',
stateless=True,
subordinate_configuration=expect)