Initial unit_tests added - NOT FUNCTIONAL at this stage

This adds in the unit_test framework but there is a name collision
between charm.openstack as a module, and charm.openstack here which the
package loader can't resolve.  Therefore, going to change the
charm.openstack package to charms.openstack to avoid the collision.
This commit is contained in:
Alex Kavanagh 2016-05-19 18:00:23 +00:00
parent c7fc7ba5e0
commit 1ea4507ced
13 changed files with 157 additions and 20 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ build
layers
interfaces
trusty
.testrepository

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

View File

@ -2,7 +2,14 @@
LAYER_PATH := layers
clean:
rm -Rf build .tox
rm -Rf build .tox .testrepository
generate: clean
LAYER_PATH=$(LAYER_PATH) tox -e generate
lint:
@tox -e lint
test:
@echo Starting unit tests...
@tox -e py27

0
src/lib/__init__.py Normal file
View File

View File

View File

View File

@ -4,9 +4,13 @@
# needed on the class.
from __future__ import absolute_import
import charmhelpers.fetch
import charmhelpers.core.hookenv as hookenv
import charmhelpers.contrib.openstack.utils as ch_utils
import charm.openstack.charm
import charm.openstack.adapters
import charmhelpers.fetch
import charm.openstack.ip as os_ip
PACKAGES = ['barbican-common', 'barbican-api', 'barbican-worker',
'python-mysqldb']
@ -30,16 +34,17 @@ def setup_amqp_req(amqp):
"""Use the amqp interface to request access to the amqp broker using our
local configuration.
"""
amqp.request_access(username=config('rabbit-user'),
vhost=config('rabbit-vhost'))
amqp.request_access(username=hookenv.config('rabbit-user'),
vhost=hookenv.config('rabbit-vhost'))
def setup_database(database):
"""On receiving database credentials, configure the database on the
interface.
"""
database.configure(config('database'), config('database-user'),
unit_private_ip())
database.configure(hookenv.config('database'),
hookenv.config('database-user'),
hookenv.unit_private_ip())
def setup_endpoint(keystone):
@ -64,11 +69,11 @@ def render_configs(interfaces_list):
###
# Implementation of the Barbican Charm classes
class BarbicanConfigurationAdapater(
class BarbicanConfigurationAdapter(
charm.openstack.adapters.ConfigurationAdapter):
def __init__(self):
super(BarbicanConfigurationAdapater, self).__init__()
super(BarbicanConfigurationAdapter, self).__init__()
if self.keystone_api_version not in ['2', '3', 'none']:
raise ValueError(
"Unsupported keystone-api-version ({}). It should be 2 or 3"
@ -107,17 +112,15 @@ class BarbicanCharm(charm.openstack.charm.OpenStackCharm):
functionality to manage a barbican unit.
"""
releases = {
'liberty': BarbicanCharm
}
# don't set releases here (as we need to self refer - see below)
first_release = 'liberty'
name = 'barbican'
packages = PACKAGES
api_ports = {
'barbican-api': {
PUBLIC: 9311,
ADMIN: 9312,
INTERNAL: 9313,
os_ip.PUBLIC: 9311,
os_ip.ADMIN: 9312,
os_ip.INTERNAL: 9313,
}
}
service_type = 'secretstore'
@ -136,14 +139,13 @@ class BarbicanCharm(charm.openstack.charm.OpenStackCharm):
"""Custom initialiser for class
If no release is passed, then the charm determines the release from the
os_release() function.
ch_utils.os_release() function.
"""
if release is None:
#release = os_release('barbican-common')
release = os_release('python-keystonemiddleware')
# release = ch_utils.os_release('barbican-common')
release = ch_utils.os_release('python-keystonemiddleware')
super(BarbicanCharm, self).__init__(release=release, **kwargs)
def install(self):
"""Customise the installation, configure the source and then call the
parent install() method to install the packages
@ -152,3 +154,11 @@ class BarbicanCharm(charm.openstack.charm.OpenStackCharm):
self.configure_source()
# and do the actual install
super(BarbicanCharm, self).install()
# Set Barbican releases here because we need it to refer to itself. For derived
# classes of BarbicanCharm for different series we would still set the releases
# here.
BarbicanCharm.releases = {
'liberty': BarbicanCharm,
}

0
src/reactive/__init__.py Normal file
View File

View File

@ -3,14 +3,18 @@ from __future__ import absolute_import
from __future__ import print_function
import sys
sys.path.append('lib')
sys.path.append('src/lib')
import charms.reactive as reactive
print(sys.path)
import os
print(os.getcwd())
print(os.path.dirname(os.path.realpath(__file__)))
# This charm's library contains all of the handler code
import charm.openstack.barbican as barbican
# use a synthetic state to ensure that it get it to be installed independent of
# the install hook.
@reactive.when_not('charm.installed')

7
test-requirements.txt Normal file
View File

@ -0,0 +1,7 @@
flake8>=2.2.4,<=2.4.1
os-testr>=0.4.1
charm-tools>=2.0.0
charms.reactive
mock>=1.2
coverage>=3.6
https://github.com/ajkavanagh/charm.openstack/zipball/master

15
tox.ini
View File

@ -18,7 +18,20 @@ deps =
[testenv:generate]
basepython = python2.7
commands =
charm build --log-level DEBUG -o {toxinidir}/build charm
charm build --log-level DEBUG -o {toxinidir}/build src
[testenv:py27]
basepython = python2.7
deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs}
[testenv:lint]
basepython = python2.7
deps = -r{toxinidir}/test-requirements.txt
commands = flake8 {posargs} src unit_tests
[testenv:venv]
commands = {posargs}
[flake8]
ignore = E402,E226

24
unit_tests/__init__.py Normal file
View File

@ -0,0 +1,24 @@
import sys
import mock
charmhelpers = mock.MagicMock()
sys.modules['charmhelpers'] = charmhelpers
sys.modules['charmhelpers.core'] = charmhelpers.core
sys.modules['charmhelpers.core.hookenv'] = charmhelpers.core.hookenv
sys.modules['charmhelpers.core.host'] = charmhelpers.core.host
sys.modules['charmhelpers.core.templating'] = charmhelpers.core.templating
sys.modules['charmhelpers.contrib'] = charmhelpers.contrib
sys.modules['charmhelpers.contrib.openstack'] = charmhelpers.contrib.openstack
sys.modules['charmhelpers.contrib.openstack.utils'] = (
charmhelpers.contrib.openstack.utils)
sys.modules['charmhelpers.contrib.openstack.templating'] = (
charmhelpers.contrib.openstack.templating)
sys.modules['charmhelpers.contrib.network'] = charmhelpers.contrib.network
sys.modules['charmhelpers.contrib.network.ip'] = (
charmhelpers.contrib.network.ip)
sys.modules['charmhelpers.fetch'] = charmhelpers.fetch
sys.modules['charmhelpers.cli'] = charmhelpers.cli
sys.modules['charmhelpers.contrib.hahelpers'] = charmhelpers.contrib.hahelpers
sys.modules['charmhelpers.contrib.hahelpers.cluster'] = (
charmhelpers.contrib.hahelpers.cluster)

View File

@ -0,0 +1,63 @@
from __future__ import absolute_import
from __future__ import print_function
import sys
import unittest
import mock
sys.path.append('src')
sys.path.append('src/lib')
import reactive.barbican_handlers as handlers
_hook_args = {}
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 TestBarbicanHandlers(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._patched_hook = mock.patch('charms.reactive.hook', mock_hook)
cls._patched_hook_started = cls._patched_hook.start()
# force requires to rerun the mock_hook decorator:
reload(requires)
@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
reload(requires)
def patch(self, attr, return_value=None):
mocked = mock.patch.object(self.kr, attr)
self._patches[attr] = mocked
started = mocked.start()
started.return_value = return_value
self._patches_start[attr] = started
setattr(self, attr, started)
def test_registered_hooks(self):
# test that the hooks actually registered the relation expressions that
# are meaningful for this interface: this is to handle regressions.
# The keys are the function names that the hook attaches to.
hook_patterns = {
'joined': ('{requires:keystone}-relation-joined', ),
'changed': ('{requires:keystone}-relation-changed', ),
'departed': ('{requires:keystone}-relation-{broken,departed}', ),
}
print(_hook_args)
# for k, v in _hook_args.items():
# self.assertEqual(hook_patterns[k], v['args'])