aboutsummaryrefslogtreecommitdiffstats
path: root/xtesting/tests/unit
diff options
context:
space:
mode:
Diffstat (limited to 'xtesting/tests/unit')
-rw-r--r--xtesting/tests/unit/__init__.py0
-rw-r--r--xtesting/tests/unit/ci/__init__.py0
-rw-r--r--xtesting/tests/unit/ci/test_run_tests.py267
-rw-r--r--xtesting/tests/unit/ci/test_tier_builder.py93
-rw-r--r--xtesting/tests/unit/ci/test_tier_handler.py139
-rw-r--r--xtesting/tests/unit/core/__init__.py0
-rw-r--r--xtesting/tests/unit/core/test_feature.py117
-rw-r--r--xtesting/tests/unit/core/test_robotframework.py199
-rw-r--r--xtesting/tests/unit/core/test_testcase.py277
-rw-r--r--xtesting/tests/unit/core/test_unit.py98
-rw-r--r--xtesting/tests/unit/core/test_vnf.py187
-rw-r--r--xtesting/tests/unit/energy/__init__.py0
-rw-r--r--xtesting/tests/unit/energy/test_functest_energy.py371
-rw-r--r--xtesting/tests/unit/utils/__init__.py0
-rw-r--r--xtesting/tests/unit/utils/test_decorators.py125
-rw-r--r--xtesting/tests/unit/utils/test_env.py57
16 files changed, 1930 insertions, 0 deletions
diff --git a/xtesting/tests/unit/__init__.py b/xtesting/tests/unit/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/xtesting/tests/unit/__init__.py
diff --git a/xtesting/tests/unit/ci/__init__.py b/xtesting/tests/unit/ci/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/xtesting/tests/unit/ci/__init__.py
diff --git a/xtesting/tests/unit/ci/test_run_tests.py b/xtesting/tests/unit/ci/test_run_tests.py
new file mode 100644
index 00000000..de2af66d
--- /dev/null
+++ b/xtesting/tests/unit/ci/test_run_tests.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+import os
+
+import mock
+
+from xtesting.ci import run_tests
+from xtesting.core.testcase import TestCase
+
+
+class FakeModule(TestCase):
+
+ def run(self, **kwargs):
+ return TestCase.EX_OK
+
+
+class RunTestsTesting(unittest.TestCase):
+
+ def setUp(self):
+ self.runner = run_tests.Runner()
+ mock_test_case = mock.Mock()
+ mock_test_case.is_successful.return_value = TestCase.EX_OK
+ self.runner.executed_test_cases['test1'] = mock_test_case
+ self.runner.executed_test_cases['test2'] = mock_test_case
+ self.sep = 'test_sep'
+ self.creds = {'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
+ 'OS_USERNAME': 'test_os_username',
+ 'OS_TENANT_NAME': 'test_tenant',
+ 'OS_PASSWORD': 'test_password'}
+ self.test = {'test_name': 'test_name'}
+ self.tier = mock.Mock()
+ test1 = mock.Mock()
+ test1.get_name.return_value = 'test1'
+ test2 = mock.Mock()
+ test2.get_name.return_value = 'test2'
+ attrs = {'get_name.return_value': 'test_tier',
+ 'get_tests.return_value': [test1, test2],
+ 'get_ci_loop.return_value': 'test_ci_loop',
+ 'get_test_names.return_value': ['test1', 'test2']}
+ self.tier.configure_mock(**attrs)
+
+ self.tiers = mock.Mock()
+ attrs = {'get_tiers.return_value': [self.tier]}
+ self.tiers.configure_mock(**attrs)
+
+ self.run_tests_parser = run_tests.RunTestsParser()
+
+ @mock.patch('xtesting.ci.run_tests.Runner.get_dict_by_test')
+ def test_get_run_dict(self, *args):
+ retval = {'run': mock.Mock()}
+ args[0].return_value = retval
+ self.assertEqual(self.runner.get_run_dict('test_name'), retval['run'])
+ args[0].assert_called_once_with('test_name')
+
+ @mock.patch('xtesting.ci.run_tests.LOGGER.error')
+ @mock.patch('xtesting.ci.run_tests.Runner.get_dict_by_test',
+ return_value=None)
+ def test_get_run_dict_config_ko(self, *args):
+ testname = 'test_name'
+ self.assertEqual(self.runner.get_run_dict(testname), None)
+ args[0].return_value = {}
+ self.assertEqual(self.runner.get_run_dict(testname), None)
+ calls = [mock.call(testname), mock.call(testname)]
+ args[0].assert_has_calls(calls)
+ calls = [mock.call("Cannot get %s's config options", testname),
+ mock.call("Cannot get %s's config options", testname)]
+ args[1].assert_has_calls(calls)
+
+ @mock.patch('xtesting.ci.run_tests.LOGGER.exception')
+ @mock.patch('xtesting.ci.run_tests.Runner.get_dict_by_test',
+ side_effect=Exception)
+ def test_get_run_dict_exception(self, *args):
+ testname = 'test_name'
+ self.assertEqual(self.runner.get_run_dict(testname), None)
+ args[1].assert_called_once_with(
+ "Cannot get %s's config options", testname)
+
+ def _test_source_envfile(self, msg, key='OS_TENANT_NAME', value='admin'):
+ try:
+ del os.environ[key]
+ except Exception: # pylint: disable=broad-except
+ pass
+ envfile = 'rc_file'
+ with mock.patch('six.moves.builtins.open',
+ mock.mock_open(read_data=msg)) as mock_method,\
+ mock.patch('os.path.isfile', return_value=True):
+ mock_method.return_value.__iter__ = lambda self: iter(
+ self.readline, '')
+ self.runner.source_envfile(envfile)
+ mock_method.assert_called_once_with(envfile, 'r')
+ self.assertEqual(os.environ[key], value)
+
+ def test_source_envfile(self):
+ self._test_source_envfile('OS_TENANT_NAME=admin')
+ self._test_source_envfile('OS_TENANT_NAME= admin')
+ self._test_source_envfile('OS_TENANT_NAME = admin')
+ self._test_source_envfile('OS_TENANT_NAME = "admin"')
+ self._test_source_envfile('export OS_TENANT_NAME=admin')
+ self._test_source_envfile('export OS_TENANT_NAME =admin')
+ self._test_source_envfile('export OS_TENANT_NAME = admin')
+ self._test_source_envfile('export OS_TENANT_NAME = "admin"')
+ # This test will fail as soon as rc_file is fixed
+ self._test_source_envfile(
+ 'export "\'OS_TENANT_NAME\'" = "\'admin\'"')
+
+ def test_get_dict_by_test(self):
+ with mock.patch('six.moves.builtins.open', mock.mock_open()), \
+ mock.patch('yaml.safe_load') as mock_yaml:
+ mock_obj = mock.Mock()
+ testcase_dict = {'case_name': 'testname',
+ 'criteria': 50}
+ attrs = {'get.return_value': [{'testcases': [testcase_dict]}]}
+ mock_obj.configure_mock(**attrs)
+ mock_yaml.return_value = mock_obj
+ self.assertDictEqual(
+ run_tests.Runner.get_dict_by_test('testname'),
+ testcase_dict)
+
+ @mock.patch('xtesting.ci.run_tests.Runner.get_run_dict',
+ return_value=None)
+ def test_run_tests_import_exception(self, *args):
+ mock_test = mock.Mock()
+ kwargs = {'get_name.return_value': 'test_name',
+ 'needs_clean.return_value': False}
+ mock_test.configure_mock(**kwargs)
+ with self.assertRaises(Exception) as context:
+ self.runner.run_test(mock_test)
+ args[0].assert_called_with('test_name')
+ msg = "Cannot import the class for the test case."
+ self.assertTrue(msg in str(context.exception))
+
+ @mock.patch('importlib.import_module', name="module",
+ return_value=mock.Mock(test_class=mock.Mock(
+ side_effect=FakeModule)))
+ @mock.patch('xtesting.ci.run_tests.Runner.get_dict_by_test')
+ def test_run_tests_default(self, *args):
+ mock_test = mock.Mock()
+ kwargs = {'get_name.return_value': 'test_name',
+ 'needs_clean.return_value': True}
+ mock_test.configure_mock(**kwargs)
+ test_run_dict = {'module': 'test_module',
+ 'class': 'test_class'}
+ with mock.patch('xtesting.ci.run_tests.Runner.get_run_dict',
+ return_value=test_run_dict):
+ self.runner.clean_flag = True
+ self.runner.run_test(mock_test)
+ args[0].assert_called_with('test_name')
+ args[1].assert_called_with('test_module')
+ self.assertEqual(self.runner.overall_result,
+ run_tests.Result.EX_OK)
+
+ @mock.patch('xtesting.ci.run_tests.Runner.run_test',
+ return_value=TestCase.EX_OK)
+ def test_run_tier_default(self, *mock_methods):
+ self.assertEqual(self.runner.run_tier(self.tier),
+ run_tests.Result.EX_OK)
+ mock_methods[0].assert_called_with(mock.ANY)
+
+ @mock.patch('xtesting.ci.run_tests.LOGGER.info')
+ def test_run_tier_missing_test(self, mock_logger_info):
+ self.tier.get_tests.return_value = None
+ self.assertEqual(self.runner.run_tier(self.tier),
+ run_tests.Result.EX_ERROR)
+ self.assertTrue(mock_logger_info.called)
+
+ @mock.patch('xtesting.ci.run_tests.LOGGER.info')
+ @mock.patch('xtesting.ci.run_tests.Runner.run_tier')
+ @mock.patch('xtesting.ci.run_tests.Runner.summary')
+ def test_run_all_default(self, *mock_methods):
+ os.environ['CI_LOOP'] = 'test_ci_loop'
+ self.runner.run_all()
+ mock_methods[1].assert_not_called()
+ self.assertTrue(mock_methods[2].called)
+
+ @mock.patch('xtesting.ci.run_tests.LOGGER.info')
+ @mock.patch('xtesting.ci.run_tests.Runner.summary')
+ def test_run_all_missing_tier(self, *mock_methods):
+ os.environ['CI_LOOP'] = 'loop_re_not_available'
+ self.runner.run_all()
+ self.assertTrue(mock_methods[1].called)
+
+ @mock.patch('xtesting.ci.run_tests.Runner.source_envfile',
+ side_effect=Exception)
+ @mock.patch('xtesting.ci.run_tests.Runner.summary')
+ def test_main_failed(self, *mock_methods):
+ kwargs = {'test': 'test_name', 'noclean': True, 'report': True}
+ args = {'get_tier.return_value': False,
+ 'get_test.return_value': False}
+ self.runner.tiers = mock.Mock()
+ self.runner.tiers.configure_mock(**args)
+ self.assertEqual(self.runner.main(**kwargs),
+ run_tests.Result.EX_ERROR)
+ mock_methods[1].assert_called_once_with()
+
+ @mock.patch('xtesting.ci.run_tests.Runner.source_envfile')
+ @mock.patch('xtesting.ci.run_tests.Runner.run_test',
+ return_value=TestCase.EX_OK)
+ @mock.patch('xtesting.ci.run_tests.Runner.summary')
+ def test_main_tier(self, *mock_methods):
+ mock_tier = mock.Mock()
+ test_mock = mock.Mock()
+ test_mock.get_name.return_value = 'test1'
+ args = {'get_name.return_value': 'tier_name',
+ 'get_tests.return_value': [test_mock]}
+ mock_tier.configure_mock(**args)
+ kwargs = {'test': 'tier_name', 'noclean': True, 'report': True}
+ args = {'get_tier.return_value': mock_tier,
+ 'get_test.return_value': None}
+ self.runner.tiers = mock.Mock()
+ self.runner.tiers.configure_mock(**args)
+ self.assertEqual(self.runner.main(**kwargs),
+ run_tests.Result.EX_OK)
+ mock_methods[1].assert_called()
+
+ @mock.patch('xtesting.ci.run_tests.Runner.source_envfile')
+ @mock.patch('xtesting.ci.run_tests.Runner.run_test',
+ return_value=TestCase.EX_OK)
+ def test_main_test(self, *mock_methods):
+ kwargs = {'test': 'test_name', 'noclean': True, 'report': True}
+ args = {'get_tier.return_value': None,
+ 'get_test.return_value': 'test_name'}
+ self.runner.tiers = mock.Mock()
+ mock_methods[1].return_value = self.creds
+ self.runner.tiers.configure_mock(**args)
+ self.assertEqual(self.runner.main(**kwargs),
+ run_tests.Result.EX_OK)
+ mock_methods[0].assert_called_once_with('test_name')
+
+ @mock.patch('xtesting.ci.run_tests.Runner.source_envfile')
+ @mock.patch('xtesting.ci.run_tests.Runner.run_all')
+ @mock.patch('xtesting.ci.run_tests.Runner.summary')
+ def test_main_all_tier(self, *args):
+ kwargs = {'get_tier.return_value': None,
+ 'get_test.return_value': None}
+ self.runner.tiers = mock.Mock()
+ self.runner.tiers.configure_mock(**kwargs)
+ self.assertEqual(
+ self.runner.main(test='all', noclean=True, report=True),
+ run_tests.Result.EX_OK)
+ args[0].assert_called_once_with(None)
+ args[1].assert_called_once_with()
+ args[2].assert_called_once_with()
+
+ @mock.patch('xtesting.ci.run_tests.Runner.source_envfile')
+ def test_main_any_tier_test_ko(self, *args):
+ kwargs = {'get_tier.return_value': None,
+ 'get_test.return_value': None}
+ self.runner.tiers = mock.Mock()
+ self.runner.tiers.configure_mock(**kwargs)
+ self.assertEqual(
+ self.runner.main(test='any', noclean=True, report=True),
+ run_tests.Result.EX_ERROR)
+ args[0].assert_called_once_with()
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/ci/test_tier_builder.py b/xtesting/tests/unit/ci/test_tier_builder.py
new file mode 100644
index 00000000..22a44a58
--- /dev/null
+++ b/xtesting/tests/unit/ci/test_tier_builder.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from xtesting.ci import tier_builder
+
+
+class TierBuilderTesting(unittest.TestCase):
+
+ def setUp(self):
+ self.dependency = {
+ 'installer': 'test_installer', 'scenario': 'test_scenario'}
+ self.testcase = {
+ 'dependencies': self.dependency, 'enabled': 'true',
+ 'case_name': 'test_name', 'criteria': 'test_criteria',
+ 'blocking': 'test_blocking', 'description': 'test_desc',
+ 'project_name': 'project_name'}
+ self.dic_tier = {
+ 'name': 'test_tier', 'order': 'test_order',
+ 'ci_loop': 'test_ci_loop', 'description': 'test_desc',
+ 'testcases': [self.testcase]}
+ self.mock_yaml = mock.Mock()
+ attrs = {'get.return_value': [self.dic_tier]}
+ self.mock_yaml.configure_mock(**attrs)
+
+ with mock.patch('xtesting.ci.tier_builder.yaml.safe_load',
+ return_value=self.mock_yaml), \
+ mock.patch('six.moves.builtins.open', mock.mock_open()):
+ self.tierbuilder = tier_builder.TierBuilder(
+ 'test_installer', 'test_scenario', 'testcases_file')
+ self.tier_obj = self.tierbuilder.tier_objects[0]
+
+ def test_get_tiers(self):
+ self.assertEqual(self.tierbuilder.get_tiers(),
+ [self.tier_obj])
+
+ def test_get_tier_names(self):
+ self.assertEqual(self.tierbuilder.get_tier_names(),
+ ['test_tier'])
+
+ def test_get_tier_present_tier(self):
+ self.assertEqual(self.tierbuilder.get_tier('test_tier'),
+ self.tier_obj)
+
+ def test_get_tier_missing_tier(self):
+ self.assertEqual(self.tierbuilder.get_tier('test_tier2'),
+ None)
+
+ def test_get_test_present_test(self):
+ self.assertEqual(self.tierbuilder.get_test('test_name'),
+ self.tier_obj.get_test('test_name'))
+
+ def test_get_test_missing_test(self):
+ self.assertEqual(self.tierbuilder.get_test('test_name2'),
+ None)
+
+ def test_get_tests_present_tier(self):
+ self.assertEqual(self.tierbuilder.get_tests('test_tier'),
+ self.tier_obj.tests_array)
+
+ def test_get_tests_missing_tier(self):
+ self.assertEqual(self.tierbuilder.get_tests('test_tier2'),
+ None)
+
+ def test_get_tier_name_ok(self):
+ self.assertEqual(self.tierbuilder.get_tier_name('test_name'),
+ 'test_tier')
+
+ def test_get_tier_name_ko(self):
+ self.assertEqual(self.tierbuilder.get_tier_name('test_name2'), None)
+
+ def test_str(self):
+ message = str(self.tierbuilder)
+ self.assertTrue('test_tier' in message)
+ self.assertTrue('test_order' in message)
+ self.assertTrue('test_ci_loop' in message)
+ self.assertTrue('test_desc' in message)
+ self.assertTrue('test_name' in message)
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/ci/test_tier_handler.py b/xtesting/tests/unit/ci/test_tier_handler.py
new file mode 100644
index 00000000..d1900103
--- /dev/null
+++ b/xtesting/tests/unit/ci/test_tier_handler.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from xtesting.ci import tier_handler
+
+
+class TierHandlerTesting(unittest.TestCase):
+ # pylint: disable=too-many-public-methods
+
+ def setUp(self):
+ self.test = mock.Mock()
+ attrs = {'get_name.return_value': 'test_name'}
+ self.test.configure_mock(**attrs)
+ self.mock_depend = mock.Mock()
+ attrs = {'get_scenario.return_value': 'test_scenario',
+ 'get_installer.return_value': 'test_installer'}
+ self.mock_depend.configure_mock(**attrs)
+ self.tier = tier_handler.Tier(
+ 'test_tier', 'test_order', 'test_ci_loop', description='test_desc')
+ self.testcase = tier_handler.TestCase(
+ 'test_name', 'true', self.mock_depend, 'test_criteria',
+ True, description='test_desc', project='project_name')
+ self.dependency = tier_handler.Dependency(
+ 'test_installer', 'test_scenario')
+ self.testcase.str = self.testcase.__str__()
+ self.dependency.str = self.dependency.__str__()
+ self.tier.str = self.tier.__str__()
+
+ def test_split_text(self):
+ test_str = 'this is for testing'
+ self.assertEqual(tier_handler.split_text(test_str, 10),
+ ['this is ', 'for ', 'testing '])
+
+ def test_add_test(self):
+ self.tier.add_test(self.test)
+ self.assertEqual(self.tier.tests_array, [self.test])
+
+ def test_get_skipped_test1(self):
+ self.assertEqual(self.tier.get_skipped_test(), [])
+
+ def test_get_skipped_test2(self):
+ self.tier.skip_test(self.test)
+ self.assertEqual(self.tier.get_skipped_test(), [self.test])
+
+ def test_get_tests(self):
+ self.tier.tests_array = [self.test]
+ self.assertEqual(self.tier.get_tests(), [self.test])
+
+ def test_get_test_names(self):
+ self.tier.tests_array = [self.test]
+ self.assertEqual(self.tier.get_test_names(), ['test_name'])
+
+ def test_get_test(self):
+ self.tier.tests_array = [self.test]
+ with mock.patch.object(self.tier, 'is_test', return_value=True):
+ self.assertEqual(self.tier.get_test('test_name'), self.test)
+
+ def test_get_test_missing_test(self):
+ self.tier.tests_array = [self.test]
+ with mock.patch.object(self.tier, 'is_test', return_value=False):
+ self.assertEqual(self.tier.get_test('test_name'), None)
+
+ def test_get_name(self):
+ self.assertEqual(self.tier.get_name(), 'test_tier')
+
+ def test_get_order(self):
+ self.assertEqual(self.tier.get_order(), 'test_order')
+
+ def test_get_ci_loop(self):
+ self.assertEqual(self.tier.get_ci_loop(), 'test_ci_loop')
+
+ def test_testcase_is_none_in_item(self):
+ self.assertEqual(tier_handler.TestCase.is_none("item"), False)
+
+ def test_testcase_is_none_no_item(self):
+ self.assertEqual(tier_handler.TestCase.is_none(None), True)
+
+ def test_testcase_is_compatible(self):
+ self.assertEqual(
+ self.testcase.is_compatible('test_installer', 'test_scenario'),
+ True)
+
+ def test_testcase_is_compatible_2(self):
+ self.assertEqual(
+ self.testcase.is_compatible('missing_installer', 'test_scenario'),
+ False)
+ self.assertEqual(
+ self.testcase.is_compatible('test_installer', 'missing_scenario'),
+ False)
+
+ @mock.patch('re.search', side_effect=TypeError)
+ def test_testcase_is_compatible3(self, *args):
+ self.assertEqual(
+ self.testcase.is_compatible('test_installer', 'test_scenario'),
+ False)
+ args[0].assert_called_once_with('test_installer', 'test_installer')
+
+ def test_testcase_get_name(self):
+ self.assertEqual(self.tier.get_name(), 'test_tier')
+
+ def test_testcase_is_enabled(self):
+ self.assertEqual(self.testcase.is_enabled(), 'true')
+
+ def test_testcase_get_criteria(self):
+ self.assertEqual(self.testcase.get_criteria(), 'test_criteria')
+
+ def test_testcase_is_blocking(self):
+ self.assertTrue(self.testcase.is_blocking())
+
+ def test_testcase_get_project(self):
+ self.assertEqual(self.testcase.get_project(), 'project_name')
+
+ def test_testcase_get_order(self):
+ self.assertEqual(self.tier.get_order(), 'test_order')
+
+ def test_testcase_get_ci_loop(self):
+ self.assertEqual(self.tier.get_ci_loop(), 'test_ci_loop')
+
+ def test_dependency_get_installer(self):
+ self.assertEqual(self.dependency.get_installer(), 'test_installer')
+
+ def test_dependency_get_scenario(self):
+ self.assertEqual(self.dependency.get_scenario(), 'test_scenario')
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/core/__init__.py b/xtesting/tests/unit/core/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/xtesting/tests/unit/core/__init__.py
diff --git a/xtesting/tests/unit/core/test_feature.py b/xtesting/tests/unit/core/test_feature.py
new file mode 100644
index 00000000..9bbe5331
--- /dev/null
+++ b/xtesting/tests/unit/core/test_feature.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from xtesting.core import feature
+from xtesting.core import testcase
+
+
+class FeatureTestingBase(unittest.TestCase):
+
+ _case_name = "foo"
+ _project_name = "bar"
+ _repo = "dir_repo_bar"
+ _cmd = "run_bar_tests.py"
+ _output_file = '/home/opnfv/xtesting/results/foo.log'
+ feature = None
+
+ @mock.patch('time.time', side_effect=[1, 2])
+ def _test_run(self, status, mock_method=None):
+ self.assertEqual(self.feature.run(cmd=self._cmd), status)
+ if status == testcase.TestCase.EX_OK:
+ self.assertEqual(self.feature.result, 100)
+ else:
+ self.assertEqual(self.feature.result, 0)
+ mock_method.assert_has_calls([mock.call(), mock.call()])
+ self.assertEqual(self.feature.start_time, 1)
+ self.assertEqual(self.feature.stop_time, 2)
+
+ def test_logger_module_ko(self):
+ with mock.patch('six.moves.builtins.open'):
+ self.feature = feature.Feature(
+ project_name=self._project_name, case_name=self._case_name)
+ self.assertEqual(self.feature.logger.name, self._case_name)
+
+ def test_logger_module(self):
+ with mock.patch('six.moves.builtins.open'):
+ self.feature = feature.Feature(
+ project_name=self._project_name, case_name=self._case_name,
+ run={'module': 'bar'})
+ self.assertEqual(self.feature.logger.name, 'bar')
+
+
+class FeatureTesting(FeatureTestingBase):
+
+ def setUp(self):
+ # logging must be disabled else it calls time.time()
+ # what will break these unit tests.
+ logging.disable(logging.CRITICAL)
+ with mock.patch('six.moves.builtins.open'):
+ self.feature = feature.Feature(
+ project_name=self._project_name, case_name=self._case_name)
+
+ def test_run_exc(self):
+ # pylint: disable=bad-continuation
+ with mock.patch.object(
+ self.feature, 'execute',
+ side_effect=Exception) as mock_method:
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+ mock_method.assert_called_once_with(cmd=self._cmd)
+
+ def test_run(self):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+
+class BashFeatureTesting(FeatureTestingBase):
+
+ def setUp(self):
+ # logging must be disabled else it calls time.time()
+ # what will break these unit tests.
+ logging.disable(logging.CRITICAL)
+ with mock.patch('six.moves.builtins.open'):
+ self.feature = feature.BashFeature(
+ project_name=self._project_name, case_name=self._case_name)
+
+ @mock.patch('subprocess.Popen')
+ def test_run_no_cmd(self, mock_subproc):
+ self.assertEqual(
+ self.feature.run(), testcase.TestCase.EX_RUN_ERROR)
+ mock_subproc.assert_not_called()
+
+ @mock.patch('subprocess.Popen')
+ def test_run_ko(self, mock_subproc):
+ with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
+ mock_obj = mock.Mock()
+ attrs = {'wait.return_value': 1}
+ mock_obj.configure_mock(**attrs)
+
+ mock_subproc.return_value = mock_obj
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+ mopen.assert_called_once_with(self._output_file, "w+")
+
+ @mock.patch('subprocess.Popen')
+ def test_run(self, mock_subproc):
+ with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
+ mock_obj = mock.Mock()
+ attrs = {'wait.return_value': 0}
+ mock_obj.configure_mock(**attrs)
+
+ mock_subproc.return_value = mock_obj
+ self._test_run(testcase.TestCase.EX_OK)
+ mopen.assert_called_once_with(self._output_file, "w+")
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/core/test_robotframework.py b/xtesting/tests/unit/core/test_robotframework.py
new file mode 100644
index 00000000..7131b7e2
--- /dev/null
+++ b/xtesting/tests/unit/core/test_robotframework.py
@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Define the classes required to fully cover robot."""
+
+import errno
+import logging
+import os
+import unittest
+
+import mock
+from robot.errors import DataError, RobotError
+from robot.result import model
+from robot.utils.robottime import timestamp_to_secs
+
+from xtesting.core import robotframework
+
+__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
+
+
+class ResultVisitorTesting(unittest.TestCase):
+
+ """The class testing ResultVisitor."""
+ # pylint: disable=missing-docstring
+
+ def setUp(self):
+ self.visitor = robotframework.ResultVisitor()
+
+ def test_empty(self):
+ self.assertFalse(self.visitor.get_data())
+
+ def test_ok(self):
+ data = {'name': 'foo',
+ 'parent': 'bar',
+ 'status': 'PASS',
+ 'starttime': "20161216 16:00:00.000",
+ 'endtime': "20161216 16:00:01.000",
+ 'elapsedtime': 1000,
+ 'text': 'Hello, World!',
+ 'critical': True}
+ test = model.TestCase(
+ name=data['name'], status=data['status'], message=data['text'],
+ starttime=data['starttime'], endtime=data['endtime'])
+ test.parent = mock.Mock()
+ config = {'name': data['parent'],
+ 'criticality.test_is_critical.return_value': data[
+ 'critical']}
+ test.parent.configure_mock(**config)
+ self.visitor.visit_test(test)
+ self.assertEqual(self.visitor.get_data(), [data])
+
+
+class ParseResultTesting(unittest.TestCase):
+
+ """The class testing RobotFramework.parse_results()."""
+ # pylint: disable=missing-docstring
+
+ _config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000',
+ 'endtime': '20161216 16:00:01.000'}
+
+ def setUp(self):
+ self.test = robotframework.RobotFramework(
+ case_name='robot', project_name='xtesting')
+
+ @mock.patch('robot.api.ExecutionResult', side_effect=DataError)
+ def test_raises_exc(self, mock_method):
+ with self.assertRaises(DataError):
+ self.test.parse_results()
+ mock_method.assert_called_once_with(
+ os.path.join(self.test.res_dir, 'output.xml'))
+
+ def _test_result(self, config, result):
+ suite = mock.Mock()
+ suite.configure_mock(**config)
+ with mock.patch('robot.api.ExecutionResult',
+ return_value=mock.Mock(suite=suite)):
+ self.test.parse_results()
+ self.assertEqual(self.test.result, result)
+ self.assertEqual(self.test.start_time,
+ timestamp_to_secs(config['starttime']))
+ self.assertEqual(self.test.stop_time,
+ timestamp_to_secs(config['endtime']))
+ self.assertEqual(self.test.details,
+ {'description': config['name'], 'tests': []})
+
+ def test_null_passed(self):
+ self._config.update({'statistics.critical.passed': 0,
+ 'statistics.critical.total': 20})
+ self._test_result(self._config, 0)
+
+ def test_no_test(self):
+ self._config.update({'statistics.critical.passed': 20,
+ 'statistics.critical.total': 0})
+ self._test_result(self._config, 0)
+
+ def test_half_success(self):
+ self._config.update({'statistics.critical.passed': 10,
+ 'statistics.critical.total': 20})
+ self._test_result(self._config, 50)
+
+ def test_success(self):
+ self._config.update({'statistics.critical.passed': 20,
+ 'statistics.critical.total': 20})
+ self._test_result(self._config, 100)
+
+
+class RunTesting(unittest.TestCase):
+
+ """The class testing RobotFramework.run()."""
+ # pylint: disable=missing-docstring
+
+ suites = ["foo"]
+ variable = []
+ variablefile = []
+
+ def setUp(self):
+ self.test = robotframework.RobotFramework(
+ case_name='robot', project_name='xtesting')
+
+ def test_exc_key_error(self):
+ self.assertEqual(self.test.run(), self.test.EX_RUN_ERROR)
+
+ @mock.patch('robot.run')
+ def _test_makedirs_exc(self, *args):
+ with mock.patch.object(self.test, 'parse_results') as mock_method:
+ self.assertEqual(
+ self.test.run(
+ suites=self.suites, variable=self.variable,
+ variablefile=self.variablefile),
+ self.test.EX_RUN_ERROR)
+ args[0].assert_not_called()
+ mock_method.asser_not_called()
+
+ @mock.patch('os.makedirs', side_effect=Exception)
+ def test_makedirs_exc(self, *args):
+ self._test_makedirs_exc()
+ args[0].assert_called_once_with(self.test.res_dir)
+
+ @mock.patch('os.makedirs', side_effect=OSError)
+ def test_makedirs_oserror(self, *args):
+ self._test_makedirs_exc()
+ args[0].assert_called_once_with(self.test.res_dir)
+
+ @mock.patch('robot.run')
+ def _test_makedirs(self, *args):
+ with mock.patch.object(self.test, 'parse_results') as mock_method:
+ self.assertEqual(
+ self.test.run(suites=self.suites, variable=self.variable),
+ self.test.EX_OK)
+ args[0].assert_called_once_with(
+ *self.suites, log='NONE', output=self.test.xml_file,
+ report='NONE', stdout=mock.ANY, variable=self.variable,
+ variablefile=self.variablefile)
+ mock_method.assert_called_once_with()
+
+ @mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, ''))
+ def test_makedirs_oserror17(self, *args):
+ self._test_makedirs()
+ args[0].assert_called_once_with(self.test.res_dir)
+
+ @mock.patch('os.makedirs')
+ def test_makedirs(self, *args):
+ self._test_makedirs()
+ args[0].assert_called_once_with(self.test.res_dir)
+
+ @mock.patch('robot.run')
+ def _test_parse_results(self, status, *args):
+ self.assertEqual(
+ self.test.run(
+ suites=self.suites, variable=self.variable,
+ variablefile=self.variablefile),
+ status)
+ args[0].assert_called_once_with(
+ *self.suites, log='NONE', output=self.test.xml_file,
+ report='NONE', stdout=mock.ANY, variable=self.variable,
+ variablefile=self.variablefile)
+
+ def test_parse_results_exc(self):
+ with mock.patch.object(self.test, 'parse_results',
+ side_effect=Exception) as mock_method:
+ self._test_parse_results(self.test.EX_RUN_ERROR)
+ mock_method.assert_called_once_with()
+
+ def test_parse_results_robot_error(self):
+ with mock.patch.object(self.test, 'parse_results',
+ side_effect=RobotError('foo')) as mock_method:
+ self._test_parse_results(self.test.EX_RUN_ERROR)
+ mock_method.assert_called_once_with()
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/core/test_testcase.py b/xtesting/tests/unit/core/test_testcase.py
new file mode 100644
index 00000000..e2f56f8f
--- /dev/null
+++ b/xtesting/tests/unit/core/test_testcase.py
@@ -0,0 +1,277 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Define the class required to fully cover testcase."""
+
+from datetime import datetime
+import json
+import logging
+import os
+import unittest
+
+from xtesting.core import testcase
+
+import mock
+import requests
+
+
+__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
+
+
+class TestCaseTesting(unittest.TestCase):
+ """The class testing TestCase."""
+
+ # pylint: disable=missing-docstring,too-many-public-methods
+
+ _case_name = "base"
+ _project_name = "xtesting"
+ _published_result = "PASS"
+ _test_db_url = "http://testresults.opnfv.org/test/api/v1/results"
+ _headers = {'Content-Type': 'application/json'}
+
+ def setUp(self):
+ self.test = testcase.TestCase(case_name=self._case_name,
+ project_name=self._project_name)
+ self.test.start_time = 1
+ self.test.stop_time = 2
+ self.test.result = 100
+ self.test.details = {"Hello": "World"}
+ os.environ['TEST_DB_URL'] = TestCaseTesting._test_db_url
+ os.environ['INSTALLER_TYPE'] = "installer_type"
+ os.environ['DEPLOY_SCENARIO'] = "scenario"
+ os.environ['NODE_NAME'] = "node_name"
+ os.environ['BUILD_TAG'] = "foo-daily-master-bar"
+
+ def test_run_unimplemented(self):
+ self.assertEqual(self.test.run(),
+ testcase.TestCase.EX_RUN_ERROR)
+
+ def _test_pushdb_missing_attribute(self):
+ self.assertEqual(self.test.push_to_db(),
+ testcase.TestCase.EX_PUSH_TO_DB_ERROR)
+
+ def test_pushdb_no_project_name(self):
+ self.test.project_name = None
+ self._test_pushdb_missing_attribute()
+
+ def test_pushdb_no_case_name(self):
+ self.test.case_name = None
+ self._test_pushdb_missing_attribute()
+
+ def test_pushdb_no_start_time(self):
+ self.test.start_time = None
+ self._test_pushdb_missing_attribute()
+
+ def test_pushdb_no_stop_time(self):
+ self.test.stop_time = None
+ self._test_pushdb_missing_attribute()
+
+ def _test_pushdb_missing_env(self, var):
+ del os.environ[var]
+ self.assertEqual(self.test.push_to_db(),
+ testcase.TestCase.EX_PUSH_TO_DB_ERROR)
+
+ def test_pushdb_no_db_url(self):
+ self._test_pushdb_missing_env('TEST_DB_URL')
+
+ def test_pushdb_no_installer_type(self):
+ self._test_pushdb_missing_env('INSTALLER_TYPE')
+
+ def test_pushdb_no_deploy_scenario(self):
+ self._test_pushdb_missing_env('DEPLOY_SCENARIO')
+
+ def test_pushdb_no_node_name(self):
+ self._test_pushdb_missing_env('NODE_NAME')
+
+ def test_pushdb_no_build_tag(self):
+ self._test_pushdb_missing_env('BUILD_TAG')
+
+ @mock.patch('requests.post')
+ def test_pushdb_bad_start_time(self, mock_function=None):
+ self.test.start_time = "1"
+ self.assertEqual(
+ self.test.push_to_db(),
+ testcase.TestCase.EX_PUSH_TO_DB_ERROR)
+ mock_function.assert_not_called()
+
+ @mock.patch('requests.post')
+ def test_pushdb_bad_end_time(self, mock_function=None):
+ self.test.stop_time = "2"
+ self.assertEqual(
+ self.test.push_to_db(),
+ testcase.TestCase.EX_PUSH_TO_DB_ERROR)
+ mock_function.assert_not_called()
+
+ def _get_data(self):
+ return {
+ "build_tag": os.environ['BUILD_TAG'],
+ "case_name": self._case_name,
+ "criteria": 'PASS' if self.test.is_successful(
+ ) == self.test.EX_OK else 'FAIL',
+ "details": self.test.details,
+ "installer": os.environ['INSTALLER_TYPE'],
+ "pod_name": os.environ['NODE_NAME'],
+ "project_name": self.test.project_name,
+ "scenario": os.environ['DEPLOY_SCENARIO'],
+ "start_date": datetime.fromtimestamp(
+ self.test.start_time).strftime('%Y-%m-%d %H:%M:%S'),
+ "stop_date": datetime.fromtimestamp(
+ self.test.stop_time).strftime('%Y-%m-%d %H:%M:%S'),
+ "version": "master"}
+
+ @mock.patch('requests.post')
+ def _test_pushdb_version(self, mock_function=None, **kwargs):
+ payload = self._get_data()
+ payload["version"] = kwargs.get("version", "unknown")
+ self.assertEqual(self.test.push_to_db(), testcase.TestCase.EX_OK)
+ mock_function.assert_called_once_with(
+ os.environ['TEST_DB_URL'],
+ data=json.dumps(payload, sort_keys=True),
+ headers=self._headers)
+
+ def test_pushdb_daily_job(self):
+ self._test_pushdb_version(version="master")
+
+ def test_pushdb_weekly_job(self):
+ os.environ['BUILD_TAG'] = 'foo-weekly-master-bar'
+ self._test_pushdb_version(version="master")
+
+ def test_pushdb_random_build_tag(self):
+ os.environ['BUILD_TAG'] = 'whatever'
+ self._test_pushdb_version(version="unknown")
+
+ @mock.patch('requests.post', return_value=mock.Mock(
+ raise_for_status=mock.Mock(
+ side_effect=requests.exceptions.HTTPError)))
+ def test_pushdb_http_errors(self, mock_function=None):
+ self.assertEqual(
+ self.test.push_to_db(),
+ testcase.TestCase.EX_PUSH_TO_DB_ERROR)
+ mock_function.assert_called_once_with(
+ os.environ['TEST_DB_URL'],
+ data=json.dumps(self._get_data(), sort_keys=True),
+ headers=self._headers)
+
+ def test_check_criteria_missing(self):
+ self.test.criteria = None
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_check_result_missing(self):
+ self.test.result = None
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_check_result_failed(self):
+ # Backward compatibility
+ # It must be removed as soon as TestCase subclasses
+ # stop setting result = 'PASS' or 'FAIL'.
+ self.test.result = 'FAIL'
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_check_result_pass(self):
+ # Backward compatibility
+ # It must be removed as soon as TestCase subclasses
+ # stop setting result = 'PASS' or 'FAIL'.
+ self.test.result = 'PASS'
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_OK)
+
+ def test_check_result_lt(self):
+ self.test.result = 50
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_check_result_eq(self):
+ self.test.result = 100
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_OK)
+
+ def test_check_result_gt(self):
+ self.test.criteria = 50
+ self.test.result = 100
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_OK)
+
+ def test_check_result_zero(self):
+ self.test.criteria = 0
+ self.test.result = 0
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_get_duration_start_ko(self):
+ self.test.start_time = None
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+ self.test.start_time = 0
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+
+ def test_get_duration_end_ko(self):
+ self.test.stop_time = None
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+ self.test.stop_time = 0
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+
+ def test_get_invalid_duration(self):
+ self.test.start_time = 2
+ self.test.stop_time = 1
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+
+ def test_get_zero_duration(self):
+ self.test.start_time = 2
+ self.test.stop_time = 2
+ self.assertEqual(self.test.get_duration(), "00:00")
+
+ def test_get_duration(self):
+ self.test.start_time = 1
+ self.test.stop_time = 180
+ self.assertEqual(self.test.get_duration(), "02:59")
+
+ def test_str_project_name_ko(self):
+ self.test.project_name = None
+ self.assertIn("<xtesting.core.testcase.TestCase object at",
+ str(self.test))
+
+ def test_str_case_name_ko(self):
+ self.test.case_name = None
+ self.assertIn("<xtesting.core.testcase.TestCase object at",
+ str(self.test))
+
+ def test_str_pass(self):
+ duration = '01:01'
+ with mock.patch.object(self.test, 'get_duration',
+ return_value=duration), \
+ mock.patch.object(self.test, 'is_successful',
+ return_value=testcase.TestCase.EX_OK):
+ message = str(self.test)
+ self.assertIn(self._project_name, message)
+ self.assertIn(self._case_name, message)
+ self.assertIn(duration, message)
+ self.assertIn('PASS', message)
+
+ def test_str_fail(self):
+ duration = '00:59'
+ with mock.patch.object(self.test, 'get_duration',
+ return_value=duration), \
+ mock.patch.object(
+ self.test, 'is_successful',
+ return_value=testcase.TestCase.EX_TESTCASE_FAILED):
+ message = str(self.test)
+ self.assertIn(self._project_name, message)
+ self.assertIn(self._case_name, message)
+ self.assertIn(duration, message)
+ self.assertIn('FAIL', message)
+
+ def test_clean(self):
+ self.assertEqual(self.test.clean(), None)
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/core/test_unit.py b/xtesting/tests/unit/core/test_unit.py
new file mode 100644
index 00000000..8afe0bde
--- /dev/null
+++ b/xtesting/tests/unit/core/test_unit.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from xtesting.core import unit
+from xtesting.core import testcase
+
+
+class PyTestSuiteRunnerTesting(unittest.TestCase):
+
+ def setUp(self):
+ self.psrunner = unit.Suite()
+ self.psrunner.suite = "foo"
+
+ @mock.patch('unittest.TestLoader')
+ def _test_run(self, mock_class=None, result=mock.Mock(),
+ status=testcase.TestCase.EX_OK):
+ with mock.patch('xtesting.core.unit.unittest.TextTestRunner.run',
+ return_value=result):
+ self.assertEqual(self.psrunner.run(), status)
+ mock_class.assert_not_called()
+
+ def test_check_suite_null(self):
+ self.assertEqual(unit.Suite().suite, None)
+ self.psrunner.suite = None
+ self._test_run(result=mock.Mock(),
+ status=testcase.TestCase.EX_RUN_ERROR)
+
+ def test_run_no_ut(self):
+ mock_result = mock.Mock(testsRun=0, errors=[], failures=[])
+ self._test_run(result=mock_result,
+ status=testcase.TestCase.EX_RUN_ERROR)
+ self.assertEqual(self.psrunner.result, 0)
+ self.assertEqual(self.psrunner.details,
+ {'errors': 0, 'failures': 0, 'stream': '',
+ 'testsRun': 0})
+ self.assertEqual(self.psrunner.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_run_result_ko(self):
+ self.psrunner.criteria = 100
+ mock_result = mock.Mock(testsRun=50, errors=[('test1', 'error_msg1')],
+ failures=[('test2', 'failure_msg1')])
+ self._test_run(result=mock_result)
+ self.assertEqual(self.psrunner.result, 96)
+ self.assertEqual(self.psrunner.details,
+ {'errors': 1, 'failures': 1, 'stream': '',
+ 'testsRun': 50})
+ self.assertEqual(self.psrunner.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_run_result_ok(self):
+ mock_result = mock.Mock(testsRun=50, errors=[],
+ failures=[])
+ self._test_run(result=mock_result)
+ self.assertEqual(self.psrunner.result, 100)
+ self.assertEqual(self.psrunner.details,
+ {'errors': 0, 'failures': 0, 'stream': '',
+ 'testsRun': 50})
+ self.assertEqual(self.psrunner.is_successful(),
+ testcase.TestCase.EX_OK)
+
+ @mock.patch('unittest.TestLoader')
+ def test_run_name_exc(self, mock_class=None):
+ mock_obj = mock.Mock(side_effect=ImportError)
+ mock_class.side_effect = mock_obj
+ self.assertEqual(self.psrunner.run(name='foo'),
+ testcase.TestCase.EX_RUN_ERROR)
+ mock_class.assert_called_once_with()
+ mock_obj.assert_called_once_with()
+
+ @mock.patch('unittest.TestLoader')
+ def test_run_name(self, mock_class=None):
+ mock_result = mock.Mock(testsRun=50, errors=[],
+ failures=[])
+ mock_obj = mock.Mock()
+ mock_class.side_effect = mock_obj
+ with mock.patch('xtesting.core.unit.unittest.TextTestRunner.run',
+ return_value=mock_result):
+ self.assertEqual(self.psrunner.run(name='foo'),
+ testcase.TestCase.EX_OK)
+ mock_class.assert_called_once_with()
+ mock_obj.assert_called_once_with()
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/core/test_vnf.py b/xtesting/tests/unit/core/test_vnf.py
new file mode 100644
index 00000000..ec8a783e
--- /dev/null
+++ b/xtesting/tests/unit/core/test_vnf.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from xtesting.core import vnf
+from xtesting.core import testcase
+from xtesting.utils import constants
+
+from snaps.openstack.os_credentials import OSCreds
+
+
+class VnfBaseTesting(unittest.TestCase):
+ """The class testing VNF."""
+ # pylint: disable=missing-docstring,too-many-public-methods
+
+ tenant_name = 'test_tenant_name'
+ tenant_description = 'description'
+
+ def setUp(self):
+ self.test = vnf.VnfOnBoarding(project='xtesting', case_name='foo')
+
+ def test_run_deploy_orch_exc(self):
+ with mock.patch.object(self.test, 'prepare'), \
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ side_effect=Exception) as mock_method, \
+ mock.patch.object(self.test, 'deploy_vnf',
+ return_value=True), \
+ mock.patch.object(self.test, 'test_vnf',
+ return_value=True):
+ self.assertEqual(self.test.run(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+ mock_method.assert_called_with()
+
+ def test_run_deploy_vnf_exc(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=True), \
+ mock.patch.object(self.test, 'deploy_vnf',
+ side_effect=Exception) as mock_method:
+ self.assertEqual(self.test.run(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+ mock_method.assert_called_with()
+
+ def test_run_test_vnf_exc(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=True), \
+ mock.patch.object(self.test, 'deploy_vnf', return_value=True), \
+ mock.patch.object(self.test, 'test_vnf',
+ side_effect=Exception) as mock_method:
+ self.assertEqual(self.test.run(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+ mock_method.assert_called_with()
+
+ def test_run_deploy_orch_ko(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=False), \
+ mock.patch.object(self.test, 'deploy_vnf',
+ return_value=True), \
+ mock.patch.object(self.test, 'test_vnf',
+ return_value=True):
+ self.assertEqual(self.test.run(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_run_vnf_deploy_ko(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=True), \
+ mock.patch.object(self.test, 'deploy_vnf',
+ return_value=False), \
+ mock.patch.object(self.test, 'test_vnf',
+ return_value=True):
+ self.assertEqual(self.test.run(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_run_vnf_test_ko(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=True), \
+ mock.patch.object(self.test, 'deploy_vnf',
+ return_value=True), \
+ mock.patch.object(self.test, 'test_vnf',
+ return_value=False):
+ self.assertEqual(self.test.run(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_run_default(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=True), \
+ mock.patch.object(self.test, 'deploy_vnf',
+ return_value=True), \
+ mock.patch.object(self.test, 'test_vnf',
+ return_value=True):
+ self.assertEqual(self.test.run(), testcase.TestCase.EX_OK)
+
+ @mock.patch('xtesting.core.vnf.OpenStackUser')
+ @mock.patch('xtesting.core.vnf.OpenStackProject')
+ @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials',
+ side_effect=Exception)
+ def test_prepare_exc1(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+ args[0].assert_called_with(os_env_file=constants.ENV_FILE)
+ args[1].assert_not_called()
+ args[2].assert_not_called()
+
+ @mock.patch('xtesting.core.vnf.OpenStackUser')
+ @mock.patch('xtesting.core.vnf.OpenStackProject', side_effect=Exception)
+ @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials')
+ def test_prepare_exc2(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+ args[0].assert_called_with(os_env_file=constants.ENV_FILE)
+ args[1].assert_called_with(mock.ANY, mock.ANY)
+ args[2].assert_not_called()
+
+ @mock.patch('xtesting.core.vnf.OpenStackUser', side_effect=Exception)
+ @mock.patch('xtesting.core.vnf.OpenStackProject')
+ @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials')
+ def test_prepare_exc3(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+ args[0].assert_called_with(os_env_file=constants.ENV_FILE)
+ args[1].assert_called_with(mock.ANY, mock.ANY)
+ args[2].assert_called_with(mock.ANY, mock.ANY)
+
+ @mock.patch('xtesting.core.vnf.OpenStackUser')
+ @mock.patch('xtesting.core.vnf.OpenStackProject')
+ @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials')
+ def test_prepare_default(self, *args):
+ self.assertEqual(self.test.prepare(), testcase.TestCase.EX_OK)
+ args[0].assert_called_with(os_env_file=constants.ENV_FILE)
+ args[1].assert_called_with(mock.ANY, mock.ANY)
+ args[2].assert_called_with(mock.ANY, mock.ANY)
+
+ def test_deploy_vnf_unimplemented(self):
+ with self.assertRaises(vnf.VnfDeploymentException):
+ self.test.deploy_vnf()
+
+ def test_test_vnf_unimplemented(self):
+ with self.assertRaises(vnf.VnfTestException):
+ self.test.test_vnf()
+
+ def test_deploy_orch_unimplemented(self):
+ self.assertTrue(self.test.deploy_orchestrator())
+
+ @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials',
+ return_value=OSCreds(
+ username='user', password='pass',
+ auth_url='http://foo.com:5000/v3', project_name='bar'),
+ side_effect=Exception)
+ def test_prepare_keystone_client_ko(self, *args):
+ with self.assertRaises(vnf.VnfPreparationException):
+ self.test.prepare()
+ args[0].assert_called_once()
+
+ def test_vnf_clean_exc(self):
+ obj = mock.Mock()
+ obj.clean.side_effect = Exception
+ self.test.created_object = [obj]
+ self.test.clean()
+ obj.clean.assert_called_with()
+
+ def test_vnf_clean(self):
+ obj = mock.Mock()
+ self.test.created_object = [obj]
+ self.test.clean()
+ obj.clean.assert_called_with()
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/energy/__init__.py b/xtesting/tests/unit/energy/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/xtesting/tests/unit/energy/__init__.py
diff --git a/xtesting/tests/unit/energy/test_functest_energy.py b/xtesting/tests/unit/energy/test_functest_energy.py
new file mode 100644
index 00000000..ea83c1ea
--- /dev/null
+++ b/xtesting/tests/unit/energy/test_functest_energy.py
@@ -0,0 +1,371 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Unitary test for energy module."""
+# pylint: disable=unused-argument
+import logging
+import os
+import unittest
+
+import mock
+import requests
+
+from xtesting.energy.energy import EnergyRecorder
+import xtesting.energy.energy as energy
+
+CASE_NAME = "UNIT_TEST_CASE"
+STEP_NAME = "UNIT_TEST_STEP"
+
+PREVIOUS_SCENARIO = "previous_scenario"
+PREVIOUS_STEP = "previous_step"
+
+
+class MockHttpResponse(object): # pylint: disable=too-few-public-methods
+ """Mock response for Energy recorder API."""
+
+ def __init__(self, text, status_code):
+ """Create an instance of MockHttpResponse."""
+ self.text = text
+ self.status_code = status_code
+
+
+API_OK = MockHttpResponse(
+ '{"status": "OK"}',
+ 200
+)
+API_KO = MockHttpResponse(
+ '{"message": "API-KO"}',
+ 500
+)
+
+RECORDER_OK = MockHttpResponse(
+ '{"environment": "UNIT_TEST",'
+ ' "step": "string",'
+ ' "scenario": "' + CASE_NAME + '"}',
+ 200
+)
+RECORDER_KO = MockHttpResponse(
+ '{"message": "An unhandled API exception occurred (MOCK)"}',
+ 500
+)
+RECORDER_NOT_FOUND = MockHttpResponse(
+ '{"message": "Recorder not found (MOCK)"}',
+ 404
+)
+
+
+# pylint: disable=too-many-public-methods
+class EnergyRecorderTest(unittest.TestCase):
+ """Energy module unitary test suite."""
+
+ case_name = CASE_NAME
+ request_headers = {'content-type': 'application/json'}
+ returned_value_to_preserve = "value"
+ exception_message_to_preserve = "exception_message"
+
+ @staticmethod
+ def _set_env_creds():
+ """Set config values."""
+ os.environ["ENERGY_RECORDER_API_URL"] = "http://pod-uri:8888"
+ os.environ["ENERGY_RECORDER_API_USER"] = "user"
+ os.environ["ENERGY_RECORDER_API_PASSWORD"] = "password"
+
+ @staticmethod
+ def _set_env_nocreds():
+ """Set config values."""
+ os.environ["ENERGY_RECORDER_API_URL"] = "http://pod-uri:8888"
+ del os.environ["ENERGY_RECORDER_API_USER"]
+ del os.environ["ENERGY_RECORDER_API_PASSWORD"]
+
+ @mock.patch('xtesting.energy.energy.requests.post',
+ return_value=RECORDER_OK)
+ def test_start(self, post_mock=None, get_mock=None):
+ """EnergyRecorder.start method (regular case)."""
+ self.test_load_config()
+ self.assertTrue(EnergyRecorder.start(self.case_name))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.requests.post',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_start_error(self, post_mock=None):
+ """EnergyRecorder.start method (error in method)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.start(self.case_name))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.EnergyRecorder.load_config',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_start_exception(self, conf_loader_mock=None):
+ """EnergyRecorder.start test with exception during execution."""
+ start_status = EnergyRecorder.start(CASE_NAME)
+ self.assertFalse(start_status)
+
+ @mock.patch('xtesting.energy.energy.requests.post',
+ return_value=RECORDER_KO)
+ def test_start_api_error(self, post_mock=None):
+ """EnergyRecorder.start method (API error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.start(self.case_name))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.requests.post',
+ return_value=RECORDER_OK)
+ def test_set_step(self, post_mock=None):
+ """EnergyRecorder.set_step method (regular case)."""
+ self.test_load_config()
+ self.assertTrue(EnergyRecorder.set_step(STEP_NAME))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"] + "/step",
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.requests.post',
+ return_value=RECORDER_KO)
+ def test_set_step_api_error(self, post_mock=None):
+ """EnergyRecorder.set_step method (API error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.set_step(STEP_NAME))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"] + "/step",
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.requests.post',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_set_step_error(self, post_mock=None):
+ """EnergyRecorder.set_step method (method error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.set_step(STEP_NAME))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"] + "/step",
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.EnergyRecorder.load_config',
+ side_effect=requests.exceptions.ConnectionError())
+ def test_set_step_connection_error(self, conf_loader_mock=None):
+ """EnergyRecorder.start test with exception during execution."""
+ step_status = EnergyRecorder.set_step(STEP_NAME)
+ self.assertFalse(step_status)
+
+ @mock.patch('xtesting.energy.energy.requests.delete',
+ return_value=RECORDER_OK)
+ def test_stop(self, delete_mock=None):
+ """EnergyRecorder.stop method (regular case)."""
+ self.test_load_config()
+ self.assertTrue(EnergyRecorder.stop())
+ delete_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.requests.delete',
+ return_value=RECORDER_KO)
+ def test_stop_api_error(self, delete_mock=None):
+ """EnergyRecorder.stop method (API Error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.stop())
+ delete_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @mock.patch('xtesting.energy.energy.requests.delete',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_stop_error(self, delete_mock=None):
+ """EnergyRecorder.stop method (method error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.stop())
+ delete_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers=self.request_headers,
+ timeout=EnergyRecorder.CONNECTION_TIMEOUT
+ )
+
+ @energy.enable_recording
+ def __decorated_method(self):
+ """Call with to energy recorder decorators."""
+ return self.returned_value_to_preserve
+
+ @energy.enable_recording
+ def __decorated_method_with_ex(self):
+ """Call with to energy recorder decorators."""
+ raise Exception(self.exception_message_to_preserve)
+
+ @mock.patch("xtesting.energy.energy.EnergyRecorder.get_current_scenario",
+ return_value=None)
+ @mock.patch("xtesting.energy.energy.EnergyRecorder")
+ def test_decorators(self,
+ recorder_mock=None,
+ cur_scenario_mock=None):
+ """Test energy module decorators."""
+ self.__decorated_method()
+ calls = [mock.call.start(self.case_name),
+ mock.call.stop()]
+ recorder_mock.assert_has_calls(calls)
+
+ @mock.patch("xtesting.energy.energy.EnergyRecorder.get_current_scenario",
+ return_value={"scenario": PREVIOUS_SCENARIO,
+ "step": PREVIOUS_STEP})
+ @mock.patch("xtesting.energy.energy.EnergyRecorder")
+ def test_decorators_with_previous(self,
+ recorder_mock=None,
+ cur_scenario_mock=None):
+ """Test energy module decorators."""
+ os.environ['NODE_NAME'] = 'MOCK_POD'
+ self._set_env_creds()
+ self.__decorated_method()
+ calls = [mock.call.start(self.case_name),
+ mock.call.submit_scenario(PREVIOUS_SCENARIO,
+ PREVIOUS_STEP)]
+ recorder_mock.assert_has_calls(calls, True)
+
+ def test_decorator_preserve_return(self):
+ """Test that decorator preserve method returned value."""
+ self.test_load_config()
+ self.assertTrue(
+ self.__decorated_method() == self.returned_value_to_preserve
+ )
+
+ @mock.patch(
+ "xtesting.energy.energy.finish_session")
+ def test_decorator_preserve_ex(self, finish_mock=None):
+ """Test that decorator preserve method exceptions."""
+ self.test_load_config()
+ with self.assertRaises(Exception) as context:
+ self.__decorated_method_with_ex()
+ self.assertTrue(
+ self.exception_message_to_preserve in str(context.exception)
+ )
+ self.assertTrue(finish_mock.called)
+
+ @mock.patch("xtesting.energy.energy.requests.get",
+ return_value=API_OK)
+ def test_load_config(self, loader_mock=None, get_mock=None):
+ """Test load config."""
+ os.environ['NODE_NAME'] = 'MOCK_POD'
+ self._set_env_creds()
+ EnergyRecorder.energy_recorder_api = None
+ EnergyRecorder.load_config()
+
+ self.assertEquals(
+ EnergyRecorder.energy_recorder_api["auth"],
+ ("user", "password")
+ )
+ self.assertEquals(
+ EnergyRecorder.energy_recorder_api["uri"],
+ "http://pod-uri:8888/recorders/environment/MOCK_POD"
+ )
+
+ @mock.patch("xtesting.energy.energy.requests.get",
+ return_value=API_OK)
+ def test_load_config_no_creds(self, loader_mock=None, get_mock=None):
+ """Test load config without creds."""
+ os.environ['NODE_NAME'] = 'MOCK_POD'
+ self._set_env_nocreds()
+ EnergyRecorder.energy_recorder_api = None
+ EnergyRecorder.load_config()
+ self.assertEquals(EnergyRecorder.energy_recorder_api["auth"], None)
+ self.assertEquals(
+ EnergyRecorder.energy_recorder_api["uri"],
+ "http://pod-uri:8888/recorders/environment/MOCK_POD"
+ )
+
+ @mock.patch("xtesting.energy.energy.requests.get",
+ return_value=API_OK)
+ def test_load_config_ex(self, loader_mock=None, get_mock=None):
+ """Test load config with exception."""
+ for key in ['NODE_NAME', 'ENERGY_RECORDER_API_URL']:
+ os.environ[key] = ''
+ with self.assertRaises(AssertionError):
+ EnergyRecorder.energy_recorder_api = None
+ EnergyRecorder.load_config()
+ self.assertEquals(EnergyRecorder.energy_recorder_api, None)
+
+ @mock.patch("xtesting.energy.energy.requests.get",
+ return_value=API_KO)
+ def test_load_config_api_ko(self, loader_mock=None, get_mock=None):
+ """Test load config with API unavailable."""
+ os.environ['NODE_NAME'] = 'MOCK_POD'
+ self._set_env_creds()
+ EnergyRecorder.energy_recorder_api = None
+ EnergyRecorder.load_config()
+ self.assertEquals(EnergyRecorder.energy_recorder_api["available"],
+ False)
+
+ @mock.patch('xtesting.energy.energy.requests.get',
+ return_value=RECORDER_OK)
+ def test_get_current_scenario(self, loader_mock=None, get_mock=None):
+ """Test get_current_scenario."""
+ os.environ['NODE_NAME'] = 'MOCK_POD'
+ self.test_load_config()
+ scenario = EnergyRecorder.get_current_scenario()
+ self.assertTrue(scenario is not None)
+
+ @mock.patch('xtesting.energy.energy.requests.get',
+ return_value=RECORDER_NOT_FOUND)
+ def test_current_scenario_not_found(self, get_mock=None):
+ """Test get current scenario not existing."""
+ os.environ['NODE_NAME'] = 'MOCK_POD'
+ self.test_load_config()
+ scenario = EnergyRecorder.get_current_scenario()
+ self.assertTrue(scenario is None)
+
+ @mock.patch('xtesting.energy.energy.requests.get',
+ return_value=RECORDER_KO)
+ def test_current_scenario_api_error(self, get_mock=None):
+ """Test get current scenario with API error."""
+ os.environ['NODE_NAME'] = 'MOCK_POD'
+ self.test_load_config()
+ scenario = EnergyRecorder.get_current_scenario()
+ self.assertTrue(scenario is None)
+
+ @mock.patch('xtesting.energy.energy.EnergyRecorder.load_config',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_current_scenario_exception(self, get_mock=None):
+ """Test get current scenario with exception."""
+ scenario = EnergyRecorder.get_current_scenario()
+ self.assertTrue(scenario is None)
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/utils/__init__.py b/xtesting/tests/unit/utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/xtesting/tests/unit/utils/__init__.py
diff --git a/xtesting/tests/unit/utils/test_decorators.py b/xtesting/tests/unit/utils/test_decorators.py
new file mode 100644
index 00000000..83b182a8
--- /dev/null
+++ b/xtesting/tests/unit/utils/test_decorators.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Define the class required to fully cover decorators."""
+
+from datetime import datetime
+import errno
+import json
+import logging
+import os
+import unittest
+
+import mock
+
+from xtesting.core import testcase
+from xtesting.utils import decorators
+
+__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
+
+DIR = '/dev'
+FILE = '{}/null'.format(DIR)
+URL = 'file://{}'.format(FILE)
+
+
+class DecoratorsTesting(unittest.TestCase):
+ # pylint: disable=missing-docstring
+
+ _case_name = 'base'
+ _project_name = 'xtesting'
+ _start_time = 1.0
+ _stop_time = 2.0
+ _result = 'PASS'
+ _version = 'unknown'
+ _build_tag = 'none'
+ _node_name = 'bar'
+ _deploy_scenario = 'foo'
+ _installer_type = 'debian'
+
+ def setUp(self):
+ os.environ['INSTALLER_TYPE'] = self._installer_type
+ os.environ['DEPLOY_SCENARIO'] = self._deploy_scenario
+ os.environ['NODE_NAME'] = self._node_name
+ os.environ['BUILD_TAG'] = self._build_tag
+
+ def test_wraps(self):
+ self.assertEqual(testcase.TestCase.push_to_db.__name__,
+ "push_to_db")
+
+ def _get_json(self):
+ stop_time = datetime.fromtimestamp(self._stop_time).strftime(
+ '%Y-%m-%d %H:%M:%S')
+ start_time = datetime.fromtimestamp(self._start_time).strftime(
+ '%Y-%m-%d %H:%M:%S')
+ data = {'project_name': self._project_name,
+ 'stop_date': stop_time, 'start_date': start_time,
+ 'case_name': self._case_name, 'build_tag': self._build_tag,
+ 'pod_name': self._node_name, 'installer': self._installer_type,
+ 'scenario': self._deploy_scenario, 'version': self._version,
+ 'details': {}, 'criteria': self._result}
+ return json.dumps(data, sort_keys=True)
+
+ def _get_testcase(self):
+ test = testcase.TestCase(
+ project_name=self._project_name, case_name=self._case_name)
+ test.start_time = self._start_time
+ test.stop_time = self._stop_time
+ test.result = 100
+ test.details = {}
+ return test
+
+ @mock.patch('requests.post')
+ def test_http_shema(self, *args):
+ os.environ['TEST_DB_URL'] = 'http://127.0.0.1'
+ test = self._get_testcase()
+ self.assertEqual(test.push_to_db(), testcase.TestCase.EX_OK)
+ args[0].assert_called_once_with(
+ 'http://127.0.0.1', data=self._get_json(),
+ headers={'Content-Type': 'application/json'})
+
+ def test_wrong_shema(self):
+ os.environ['TEST_DB_URL'] = '/dev/null'
+ test = self._get_testcase()
+ self.assertEqual(
+ test.push_to_db(), testcase.TestCase.EX_PUSH_TO_DB_ERROR)
+
+ def _test_dump(self):
+ os.environ['TEST_DB_URL'] = URL
+ with mock.patch.object(decorators, 'open', mock.mock_open(),
+ create=True) as mock_open:
+ test = self._get_testcase()
+ self.assertEqual(test.push_to_db(), testcase.TestCase.EX_OK)
+ mock_open.assert_called_once_with(FILE, 'a')
+ handle = mock_open()
+ call_args, _ = handle.write.call_args
+ self.assertIn('POST', call_args[0])
+ self.assertIn(self._get_json(), call_args[0])
+
+ @mock.patch('os.makedirs')
+ def test_default_dump(self, mock_method=None):
+ self._test_dump()
+ mock_method.assert_called_once_with(DIR)
+
+ @mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, ''))
+ def test_makedirs_dir_exists(self, mock_method=None):
+ self._test_dump()
+ mock_method.assert_called_once_with(DIR)
+
+ @mock.patch('os.makedirs', side_effect=OSError)
+ def test_makedirs_exc(self, *args):
+ os.environ['TEST_DB_URL'] = URL
+ test = self._get_testcase()
+ self.assertEqual(
+ test.push_to_db(), testcase.TestCase.EX_PUSH_TO_DB_ERROR)
+ args[0].assert_called_once_with(DIR)
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/xtesting/tests/unit/utils/test_env.py b/xtesting/tests/unit/utils/test_env.py
new file mode 100644
index 00000000..08601fa5
--- /dev/null
+++ b/xtesting/tests/unit/utils/test_env.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2018 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import os
+import unittest
+
+from six.moves import reload_module
+
+from xtesting.utils import env
+
+
+class EnvTesting(unittest.TestCase):
+ # pylint: disable=missing-docstring
+
+ def setUp(self):
+ os.environ['FOO'] = 'foo'
+ os.environ['BUILD_TAG'] = 'master'
+ os.environ['CI_LOOP'] = 'weekly'
+
+ def test_get_unset_unknown_env(self):
+ del os.environ['FOO']
+ self.assertEqual(env.get('FOO'), None)
+
+ def test_get_unknown_env(self):
+ self.assertEqual(env.get('FOO'), 'foo')
+ reload_module(env)
+
+ def test_get_unset_env(self):
+ del os.environ['CI_LOOP']
+ self.assertEqual(
+ env.get('CI_LOOP'), env.INPUTS['CI_LOOP'])
+
+ def test_get_env(self):
+ self.assertEqual(
+ env.get('CI_LOOP'), 'weekly')
+
+ def test_get_unset_env2(self):
+ del os.environ['BUILD_TAG']
+ self.assertEqual(
+ env.get('BUILD_TAG'), env.INPUTS['BUILD_TAG'])
+
+ def test_get_env2(self):
+ self.assertEqual(env.get('BUILD_TAG'), 'master')
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)