Add unit tests

This commit is contained in:
Liam Young 2019-03-20 09:20:01 +00:00
parent 48b67f6078
commit acad5c7d95
7 changed files with 224 additions and 60 deletions

13
.gitignore vendored
View File

@ -1,7 +1,8 @@
build/ build
.local/ .tox
.testrepository/ layers
.tox/ interfaces
func-results.json trusty
test-charm/ .testrepository
__pycache__ __pycache__
.stestr

3
.stestr.conf Normal file
View File

@ -0,0 +1,3 @@
[DEFAULT]
test_path=./unit_tests
top_dir=./

View File

@ -35,7 +35,7 @@ def render_config(*args):
available. available.
""" """
with charm.provide_charm_instance() as charm_class: with charm.provide_charm_instance() as charm_class:
# charm_class.upgrade_if_available(args) charm_class.upgrade_if_available(args)
charm_class.render_with_interfaces(args) charm_class.render_with_interfaces(args)
charm_class.assess_status() charm_class.assess_status()
reactive.set_state('config.rendered') reactive.set_state('config.rendered')

72
tox.ini
View File

@ -3,21 +3,9 @@
# within individual charm repos. # within individual charm repos.
[tox] [tox]
skipsdist = True skipsdist = True
envlist = pep8,py34,py35,py27 envlist = pep8,py34,py35
skip_missing_interpreters = True skip_missing_interpreters = True
[bundleenv]
setenv = VIRTUAL_ENV={envdir}
PYTHONHASHSEED=0
TERM=linux
LAYER_PATH={toxinidir}/layers
INTERFACE_PATH={toxinidir}/interfaces
JUJU_REPOSITORY={toxinidir}/build
install_command =
pip install {opts} {packages}
deps =
-r{toxinidir}/requirements.txt
[testenv] [testenv]
setenv = VIRTUAL_ENV={envdir} setenv = VIRTUAL_ENV={envdir}
PYTHONHASHSEED=0 PYTHONHASHSEED=0
@ -25,7 +13,7 @@ setenv = VIRTUAL_ENV={envdir}
LAYER_PATH={toxinidir}/layers LAYER_PATH={toxinidir}/layers
INTERFACE_PATH={toxinidir}/interfaces INTERFACE_PATH={toxinidir}/interfaces
JUJU_REPOSITORY={toxinidir}/build JUJU_REPOSITORY={toxinidir}/build
passenv = http_proxy https_proxy CHARM_TEMPLATE_LOCAL_BRANCH passenv = http_proxy https_proxy
install_command = install_command =
pip install {opts} {packages} pip install {opts} {packages}
deps = deps =
@ -36,36 +24,66 @@ basepython = python2.7
commands = commands =
charm-build --log-level DEBUG -o {toxinidir}/build src {posargs} charm-build --log-level DEBUG -o {toxinidir}/build src {posargs}
[testenv:py27]
basepython = python2.7
# Reactive source charms are Python3-only, but a py27 unit test target
# is required by OpenStack Governance. Remove this shim as soon as
# permitted. https://governance.openstack.org/tc/reference/cti/python_cti.html
whitelist_externals = true
commands = true
[testenv:py34] [testenv:py34]
basepython = python3.4 basepython = python3.4
deps = -r{toxinidir}/test-requirements.txt deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs} commands = stestr run {posargs}
[testenv:py35] [testenv:py35]
basepython = python3.5 basepython = python3.5
deps = -r{toxinidir}/test-requirements.txt deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs} commands = stestr run {posargs}
[testenv:py36]
basepython = python3.6
deps = -r{toxinidir}/test-requirements.txt
commands = stestr run {posargs}
[testenv:pep8] [testenv:pep8]
basepython = python2.7 basepython = python3
deps = -r{toxinidir}/test-requirements.txt deps = -r{toxinidir}/test-requirements.txt
commands = flake8 {posargs} src unit_tests commands = flake8 {posargs} src unit_tests
[testenv:test_create] [testenv:cover]
# This tox target is used for template generation testing and can be removed # Technique based heavily upon
# from a generated source charm or built charm # https://github.com/openstack/nova/blob/master/tox.ini
basepython = python2.7 basepython = python3
deps = -r{toxinidir}/test-generate-requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
setenv = setenv =
CHARM_TEMPLATE_ALT_REPO = {toxinidir} {[testenv]setenv}
PYTHON=coverage run
commands = commands =
charm-create -t openstack-api -a congress test-charm coverage erase
/bin/cp test-artifacts/congress.conf.sample {toxinidir}/test-charm/congress/src/templates/congress.conf stestr run {posargs}
# charm-build --log-level DEBUG -o {toxinidir}/test-charm/congress/build {toxinidir}/test-charm/congress/src {posargs} coverage combine
coverage html -d cover
coverage xml -o cover/coverage.xml
coverage report
[coverage:run]
branch = True
concurrency = multiprocessing
parallel = True
source =
.
omit =
.tox/*
*/charmhelpers/*
unit_tests/*
[testenv:venv] [testenv:venv]
basepython = python3
commands = {posargs} commands = {posargs}
[flake8] [flake8]
# E402 ignore necessary for path append before sys module import in actions # E402 ignore necessary for path append before sys module import in actions
ignore = E402 ignore = E402

View File

@ -13,34 +13,10 @@
# limitations under the License. # limitations under the License.
import sys import sys
import mock
sys.path.append('src') sys.path.append('src')
sys.path.append('src/lib') sys.path.append('src/lib')
# Mock out charmhelpers so that we can test without it. # Mock out charmhelpers so that we can test without it.
# also stops sideeffects from occuring. import charms_openstack.test_mocks # noqa
charmhelpers = mock.MagicMock() charms_openstack.test_mocks.mock_charmhelpers()
apt_pkg = mock.MagicMock()
sys.modules['apt_pkg'] = apt_pkg
sys.modules['charmhelpers'] = charmhelpers
sys.modules['charmhelpers.core'] = charmhelpers.core
sys.modules['charmhelpers.core.decorators'] = charmhelpers.core.decorators
sys.modules['charmhelpers.core.hookenv'] = charmhelpers.core.hookenv
sys.modules['charmhelpers.core.host'] = charmhelpers.core.host
sys.modules['charmhelpers.core.unitdata'] = charmhelpers.core.unitdata
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,86 @@
# Copyright 2019 Canonical Ltd
#
# 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.
from __future__ import absolute_import
from __future__ import print_function
import mock
import charmhelpers
import charm.openstack.masakari as masakari
import charms_openstack.test_utils as test_utils
import charms_openstack.charm
class Helper(test_utils.PatchHelper):
def setUp(self):
super().setUp()
self.patch_release(masakari.MasakariCharm.release)
class TestMasakariCharm(Helper):
def _patch_config_and_charm(self, config):
self.patch_object(charmhelpers.core.hookenv, 'config')
def cf(key=None):
if key is not None:
return config[key]
return config
self.config.side_effect = cf
c = masakari.MasakariCharm()
return c
def test_get_amqp_credentials(self):
c = self._patch_config_and_charm({})
self.assertEqual(
c.get_amqp_credentials(),
('masakari', 'masakari'))
def test_get_database_setup(self):
c = self._patch_config_and_charm({})
self.assertEqual(
c.get_database_setup(),
[{'database': 'masakari', 'username': 'masakari'}])
def test_public_url(self):
self.patch_object(charms_openstack.charm.HAOpenStackCharm,
'public_url', new_callable=mock.PropertyMock)
c = self._patch_config_and_charm({})
self.public_url.return_value = 'http://masakari-public'
self.assertEqual(
c.public_url,
'http://masakari-public/v1/%(tenant_id)s')
def test_admin_url(self):
self.patch_object(charms_openstack.charm.HAOpenStackCharm,
'admin_url', new_callable=mock.PropertyMock)
c = self._patch_config_and_charm({})
self.admin_url.return_value = 'http://masakari-admin'
self.assertEqual(
c.admin_url,
'http://masakari-admin/v1/%(tenant_id)s')
def test_internal_url(self):
self.patch_object(charms_openstack.charm.HAOpenStackCharm,
'internal_url', new_callable=mock.PropertyMock)
c = self._patch_config_and_charm({})
self.internal_url.return_value = 'http://masakari-internal'
self.assertEqual(
c.internal_url,
'http://masakari-internal/v1/%(tenant_id)s')

View File

@ -0,0 +1,80 @@
# Copyright 2019 Canonical Ltd
#
# 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.
from __future__ import absolute_import
from __future__ import print_function
import mock
import reactive.masakari_handlers as handlers
import charms_openstack.test_utils as test_utils
class TestRegisteredHooks(test_utils.TestRegisteredHooks):
def test_hooks(self):
defaults = [
'charm.installed',
'amqp.connected',
'shared-db.connected',
'identity-service.connected',
'identity-service.available', # enables SSL support
'config.changed',
'update-status']
hook_set = {
'when': {
'render_config': (
'shared-db.available',
'identity-service.available',
'amqp.available', ),
'init_db': ('config.rendered', ),
'cluster_connected': ('ha.connected', )}
}
self.registered_hooks_test_helper(handlers, hook_set, defaults)
class TestRenderStuff(test_utils.PatchHelper):
def _patch_provide_charm_instance(self):
masakari_charm = mock.MagicMock()
self.patch('charms_openstack.charm.provide_charm_instance',
name='provide_charm_instance',
new=mock.MagicMock())
self.provide_charm_instance().__enter__.return_value = masakari_charm
self.provide_charm_instance().__exit__.return_value = None
return masakari_charm
def test_render_config(self):
self.patch('charms.reactive.set_state', name='set_state')
masakari_charm = self._patch_provide_charm_instance()
handlers.render_config('keystone', 'shared-db', 'amqp')
masakari_charm.upgrade_if_available.assert_called_once_with(
('keystone', 'shared-db', 'amqp'))
masakari_charm.render_with_interfaces.assert_called_once_with(
('keystone', 'shared-db', 'amqp'))
masakari_charm.assess_status.assert_called_once_with()
self.set_state.assert_called_once_with('config.rendered')
def test_init_db(self):
masakari_charm = self._patch_provide_charm_instance()
handlers.init_db()
masakari_charm.db_sync.assert_called_once_with()
def test_cluster_connected(self):
masakari_charm = self._patch_provide_charm_instance()
handlers.cluster_connected('hacluster')
masakari_charm.configure_ha_resources.assert_called_once_with(
'hacluster')
masakari_charm.assess_status.assert_called_once_with()