Migrate unit test to testtools
Additional changes: * Removed testing framework for MuranoPL since it was based on Nose * Made test_log run only on Linux hosts * Every testcase is now required to have proper setUp method Change-Id: I86ee5ec487019c2d1b77f0fd34f748cf9c6412a0 Implements: blueprint migrate-murano-ut-to-testtoools
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -12,6 +12,9 @@ dist/
|
||||
.tox
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
.testrepository
|
||||
.coverage
|
||||
cover
|
||||
|
||||
#Python
|
||||
*.pyc
|
||||
|
7
.testr.conf
Executable file
7
.testr.conf
Executable file
@@ -0,0 +1,7 @@
|
||||
[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 $DISCOVER_DIRECTORY $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
20
murano/tests/base.py
Normal file
20
murano/tests/base.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
|
||||
import testtools
|
||||
|
||||
|
||||
class MuranoTestCase(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(MuranoTestCase, self).setUp()
|
@@ -12,12 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from murano.common.helpers import token_sanitizer
|
||||
from murano.tests import base
|
||||
|
||||
|
||||
class TokenSanitizerTests(unittest.TestCase):
|
||||
class TokenSanitizerTests(base.MuranoTestCase):
|
||||
sanitizer = token_sanitizer.TokenSanitizer()
|
||||
|
||||
def test_dict_with_one_value(self):
|
||||
|
@@ -12,12 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from murano.common import utils
|
||||
from murano.tests import base
|
||||
|
||||
|
||||
class IsDifferentTests(unittest.TestCase):
|
||||
class IsDifferentTests(base.MuranoTestCase):
|
||||
def test_equal_dicts(self):
|
||||
obj1 = {'first': 10, 'second': 12}
|
||||
obj2 = {'second': 12, 'first': 10}
|
||||
|
@@ -12,12 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from murano.common import utils
|
||||
from murano.tests import base
|
||||
|
||||
|
||||
class TraverseHelperTests(unittest.TestCase):
|
||||
class TraverseHelperTests(base.MuranoTestCase):
|
||||
def test_root_get_with_dict(self):
|
||||
source = {'attr': True}
|
||||
value = utils.TraverseHelper.get('/', source)
|
||||
|
@@ -1,17 +0,0 @@
|
||||
Namespaces:
|
||||
=: io.murano.language.tests
|
||||
|
||||
Name: ExampleTestCase
|
||||
|
||||
Extends: TestCase
|
||||
|
||||
Workflow:
|
||||
testSum:
|
||||
Body:
|
||||
- $sum: 1 + 2
|
||||
- $.assertEqual(3, $sum)
|
||||
|
||||
testUpper:
|
||||
Body:
|
||||
- $uppedValue: toUpper('test')
|
||||
- $.assertEqual('TEST', $uppedValue)
|
@@ -1,9 +0,0 @@
|
||||
Format: 1.0
|
||||
Type: Library
|
||||
FullName: io.murano.language.tests
|
||||
Name: Example Test Cases
|
||||
Description: Simple test case intended to be used as example
|
||||
Author: Example
|
||||
Tags: [test, example]
|
||||
Classes:
|
||||
io.murano.language.tests.ExampleTestCase: ExampleTestCase.yaml
|
@@ -1,158 +0,0 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import inspect
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import yaml
|
||||
|
||||
import nose
|
||||
import unittest2 as unittest
|
||||
|
||||
from murano.common import uuidutils
|
||||
from murano.dsl import executor
|
||||
from murano.dsl import murano_class
|
||||
from murano.dsl import namespace_resolver
|
||||
from murano.engine import simple_cloader
|
||||
from murano.engine.system import system_objects
|
||||
|
||||
|
||||
LOG = logging.getLogger('nose.plugins.munit')
|
||||
|
||||
|
||||
@murano_class.classname('io.murano.language.tests.TestCase')
|
||||
class BaseTestCase(object):
|
||||
pass
|
||||
|
||||
|
||||
class ManifestClassLoader(simple_cloader.SimpleClassLoader):
|
||||
def __init__(self, base_loader, base_path):
|
||||
self._base_loader = base_loader
|
||||
super(ManifestClassLoader, self).__init__(base_path)
|
||||
|
||||
def load_definition(self, name):
|
||||
manifest_file = os.path.join(self._base_path, 'manifest.yaml')
|
||||
if not os.path.exists(manifest_file):
|
||||
return None
|
||||
|
||||
with open(manifest_file) as stream:
|
||||
manifest = yaml.load(stream)
|
||||
pkg_classes = manifest.get('Classes', {})
|
||||
|
||||
if name in pkg_classes:
|
||||
class_file = os.path.join(self._base_path, pkg_classes[name])
|
||||
with open(class_file) as stream:
|
||||
return yaml.load(stream)
|
||||
else:
|
||||
return self._base_loader.load_definition(name)
|
||||
|
||||
|
||||
class MUnitTestCase(unittest.TestCase):
|
||||
def __init__(self, loader, test_case, case_name):
|
||||
self._executor = executor.MuranoDslExecutor(loader)
|
||||
self._test_case = self._executor.load(test_case)
|
||||
self._case_name = case_name
|
||||
self.register_asserts()
|
||||
super(MUnitTestCase, self).__init__(methodName='runTest')
|
||||
|
||||
def register_asserts(self):
|
||||
for item in dir(self):
|
||||
method = getattr(self, item)
|
||||
if ((inspect.ismethod(method) or inspect.isfunction(method))
|
||||
and item.startswith('assert')):
|
||||
self._test_case.type.add_method(item, method)
|
||||
|
||||
def runTest(self):
|
||||
self._test_case.type.invoke(self._case_name, self._executor,
|
||||
self._test_case, {})
|
||||
|
||||
def __repr__(self):
|
||||
return "{0} ({1})".format(self._case_name, self._test_case.type.name)
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
|
||||
class MuranoPLUnitTestPlugin(nose.plugins.Plugin):
|
||||
name = 'munit'
|
||||
|
||||
def options(self, parser, env=os.environ):
|
||||
parser.add_option('--metadata-dir')
|
||||
super(MuranoPLUnitTestPlugin, self).options(parser, env=env)
|
||||
|
||||
def configure(self, options, conf):
|
||||
self._metadata_dir = options.metadata_dir
|
||||
super(MuranoPLUnitTestPlugin, self).configure(options, conf)
|
||||
|
||||
def loadTestsFromFile(self, filename):
|
||||
with open(filename) as stream:
|
||||
manifest = yaml.load(stream)
|
||||
pkg_directory = os.path.dirname(filename)
|
||||
|
||||
base_cloader = simple_cloader.SimpleClassLoader(self._metadata_dir)
|
||||
cloader = ManifestClassLoader(base_cloader, pkg_directory)
|
||||
system_objects.register(cloader, pkg_directory)
|
||||
cloader.import_class(BaseTestCase)
|
||||
|
||||
package_classes = manifest.get('Classes', {})
|
||||
for class_name, class_file in package_classes.iteritems():
|
||||
class_file = os.path.join(pkg_directory, class_file)
|
||||
with open(class_file) as stream:
|
||||
class_definition = yaml.load(stream)
|
||||
|
||||
if not self._is_test_suite(class_definition):
|
||||
yield None
|
||||
|
||||
test_object = self._get_test_object(class_name, class_file)
|
||||
|
||||
test_cases = class_definition.get('Workflow', {})
|
||||
for case_name, _ in test_cases.iteritems():
|
||||
yield MUnitTestCase(cloader, test_object, case_name)
|
||||
|
||||
yield None
|
||||
|
||||
@staticmethod
|
||||
def _get_test_object(class_name, class_file):
|
||||
class_file = os.path.abspath(class_file)
|
||||
|
||||
extension_length = os.path.splitext(class_file)
|
||||
object_file = class_file[:-len(extension_length)] + 'json'
|
||||
|
||||
if os.path.exists(object_file):
|
||||
with open(object_file) as stream:
|
||||
return json.load(stream)
|
||||
else:
|
||||
return {
|
||||
"Objects": {
|
||||
"?": {
|
||||
"id": uuidutils.generate_uuid(),
|
||||
"type": class_name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _is_test_suite(class_definition):
|
||||
namespaces = class_definition.get('Namespaces', {})
|
||||
extends = class_definition.get('Extends')
|
||||
|
||||
ns_resolver = namespace_resolver.NamespaceResolver(namespaces)
|
||||
parent_name = ns_resolver.resolve_name(extends)
|
||||
|
||||
return parent_name == 'io.murano.language.tests.TestCase'
|
||||
|
||||
def wantFile(self, file):
|
||||
if file.endswith('manifest.yaml'):
|
||||
return True
|
@@ -16,7 +16,6 @@
|
||||
import re
|
||||
|
||||
import mock
|
||||
import unittest2 as unittest
|
||||
import yaql
|
||||
|
||||
import murano.dsl.exceptions as exceptions
|
||||
@@ -26,11 +25,16 @@ import murano.dsl.murano_object as murano_object
|
||||
import murano.dsl.namespace_resolver as ns_resolver
|
||||
import murano.dsl.typespec as typespec
|
||||
import murano.dsl.yaql_expression as yaql_expression
|
||||
from murano.tests import base
|
||||
|
||||
ROOT_CLASS = 'io.murano.Object'
|
||||
|
||||
|
||||
class TestNamespaceResolving(unittest.TestCase):
|
||||
class TestNamespaceResolving(base.MuranoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNamespaceResolving, self).setUp()
|
||||
|
||||
def test_fails_w_empty_name(self):
|
||||
resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
|
||||
|
||||
@@ -110,9 +114,12 @@ class Bunch(object):
|
||||
setattr(self, key, value)
|
||||
|
||||
|
||||
class TestClassesManipulation(unittest.TestCase):
|
||||
class TestClassesManipulation(base.MuranoTestCase):
|
||||
resolver = mock.Mock(resolve_name=lambda name: name)
|
||||
|
||||
def setUp(self):
|
||||
super(TestClassesManipulation, self).setUp()
|
||||
|
||||
def test_class_name(self):
|
||||
cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS, None)
|
||||
|
||||
@@ -152,8 +159,9 @@ class TestClassesManipulation(unittest.TestCase):
|
||||
|
||||
self.assertRaises(TypeError, cls.add_property, **kwargs)
|
||||
|
||||
@unittest.skip
|
||||
def test_add_property_to_class(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
prop = typespec.PropertySpec({'Default': 1}, self.resolver)
|
||||
cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS, None)
|
||||
cls.add_property('firstPrime', prop)
|
||||
@@ -164,8 +172,9 @@ class TestClassesManipulation(unittest.TestCase):
|
||||
self.assertEqual(['firstPrime'], class_properties)
|
||||
self.assertEqual(prop, class_property)
|
||||
|
||||
@unittest.skip
|
||||
def test_class_property_search(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
void_prop = typespec.PropertySpec({'Default': 'Void'}, self.resolver)
|
||||
mother_prop = typespec.PropertySpec({'Default': 'Mother'},
|
||||
self.resolver)
|
||||
@@ -224,8 +233,11 @@ class TestClassesManipulation(unittest.TestCase):
|
||||
self.assertFalse(obj.initialize.called)
|
||||
|
||||
|
||||
class TestObjectsManipulation(unittest.TestCase):
|
||||
class TestObjectsManipulation(base.MuranoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestObjectsManipulation, self).setUp()
|
||||
|
||||
self.resolver = mock.Mock(resolve_name=lambda name: name)
|
||||
self.cls = mock.Mock()
|
||||
self.cls.name = ROOT_CLASS
|
||||
@@ -275,8 +287,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
|
||||
self.assertEqual(parent, obj.parent)
|
||||
|
||||
@unittest.skip
|
||||
def test_fails_internal_property_access(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
|
||||
cls.add_property('__hidden',
|
||||
@@ -285,8 +298,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
|
||||
self.assertRaises(AttributeError, lambda: obj.__hidden)
|
||||
|
||||
@unittest.skip
|
||||
def test_proper_property_access(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
|
||||
cls.add_property('someProperty',
|
||||
@@ -295,8 +309,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
|
||||
self.assertEqual(0, obj.someProperty)
|
||||
|
||||
@unittest.skip
|
||||
def test_parent_class_property_access(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
child_cls = murano_class.MuranoClass(None, self.resolver,
|
||||
'Child', [cls])
|
||||
@@ -307,8 +322,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
|
||||
self.assertEqual(0, obj.anotherProperty)
|
||||
|
||||
@unittest.skip
|
||||
def test_fails_on_parents_property_collision(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
mother = murano_class.MuranoClass(None, self.resolver,
|
||||
'Mother', [root])
|
||||
@@ -344,8 +360,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
|
||||
self.assertEqual(prop_value, resolved_value)
|
||||
|
||||
@unittest.skip
|
||||
def test_fails_forbidden_set_property(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
cls.add_property('someProperty',
|
||||
typespec.PropertySpec({'Default': 0}, self.resolver))
|
||||
@@ -355,8 +372,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
self.assertRaises(exceptions.NoWriteAccess, obj.set_property,
|
||||
'someProperty', 10, caller_class=cls)
|
||||
|
||||
@unittest.skip
|
||||
def test_set_property(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
cls.add_property('someProperty',
|
||||
typespec.PropertySpec({'Default': 0}, self.resolver))
|
||||
@@ -369,8 +387,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
|
||||
self.assertEqual(10, obj.someProperty)
|
||||
|
||||
@unittest.skip
|
||||
def test_set_parent_property(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
cls = murano_class.MuranoClass(None, self.resolver,
|
||||
'SomeClass', [root])
|
||||
@@ -385,8 +404,9 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
|
||||
self.assertEqual(20, obj.rootProperty)
|
||||
|
||||
@unittest.skip
|
||||
def test_object_up_cast(self):
|
||||
self.skipTest("FIXME!")
|
||||
|
||||
root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
|
||||
root_alt = murano_class.MuranoClass(None, self.resolver, 'RootAlt', [])
|
||||
cls = murano_class.MuranoClass(
|
||||
@@ -413,7 +433,11 @@ class TestObjectsManipulation(unittest.TestCase):
|
||||
self.assertRaises(TypeError, root_obj.cast, cls)
|
||||
|
||||
|
||||
class TestHelperFunctions(unittest.TestCase):
|
||||
class TestHelperFunctions(base.MuranoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestHelperFunctions, self).setUp()
|
||||
|
||||
def test_generate_id(self):
|
||||
generated_id = helpers.generate_id()
|
||||
|
||||
@@ -452,7 +476,11 @@ class TestHelperFunctions(unittest.TestCase):
|
||||
self.assertTrue(testee([yaql_expr]))
|
||||
|
||||
|
||||
class TestYaqlExpression(unittest.TestCase):
|
||||
class TestYaqlExpression(base.MuranoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestYaqlExpression, self).setUp()
|
||||
|
||||
def test_expression(self):
|
||||
yaql_expr = yaql_expression.YaqlExpression('string')
|
||||
|
||||
|
@@ -12,15 +12,23 @@
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
from murano.openstack.common import log
|
||||
from murano.tests import base
|
||||
|
||||
|
||||
class SysLogHandlersTestCase(unittest.TestCase):
|
||||
class SysLogHandlersTestCase(base.MuranoTestCase):
|
||||
"""Test for standard and RFC compliant Syslog handlers."""
|
||||
|
||||
def setUp(self):
|
||||
super(SysLogHandlersTestCase, self).setUp()
|
||||
|
||||
if sys.platform != 'linux2':
|
||||
self.skip("SKIP: This test work on Linux platform only.")
|
||||
|
||||
self.facility = logging.handlers.SysLogHandler.LOG_USER
|
||||
self.rfclogger = log.RFCSysLogHandler(address='/dev/log',
|
||||
facility=self.facility)
|
||||
|
@@ -1,14 +1,13 @@
|
||||
hacking>=0.8.0,<0.9
|
||||
|
||||
unittest2
|
||||
coverage>=3.6
|
||||
discover
|
||||
fixtures>=0.3.14
|
||||
mox>=0.5.3
|
||||
nose
|
||||
nose-exclude
|
||||
openstack.nose_plugin>=0.7
|
||||
nosehtmloutput>=0.0.3
|
||||
sphinx>=1.1.2,<1.2
|
||||
requests>=1.1
|
||||
testtools>=0.9.34
|
||||
mock>=1.0
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=0.9.34
|
||||
unittest2
|
||||
|
||||
# doc build requirements
|
||||
sphinx>=1.1.2,<1.2
|
||||
|
14
tox.ini
14
tox.ini
@@ -6,15 +6,13 @@ skipsdist = True
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
NOSE_WITH_OPENSTACK=1
|
||||
NOSE_OPENSTACK_COLOR=1
|
||||
NOSE_OPENSTACK_RED=0.05
|
||||
NOSE_OPENSTACK_YELLOW=0.025
|
||||
NOSE_OPENSTACK_SHOW_ELAPSED=1
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
DISCOVER_DIRECTORY=murano/tests
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = nosetests -w murano/tests
|
||||
commands = python setup.py test --slowest --testr-args="{posargs}"
|
||||
whitelist_externals = bash
|
||||
|
||||
[testenv:pep8]
|
||||
commands =
|
||||
@@ -24,7 +22,7 @@ commands =
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
commands = nosetests --cover-erase --cover-package=murano --with-xcoverage
|
||||
commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
|
||||
[testenv:docs]
|
||||
commands =
|
||||
|
Reference in New Issue
Block a user