summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--docker/Dockerfile9
-rw-r--r--docker/Dockerfile.aarch645
-rw-r--r--docs/api/_static/.gitkeep0
-rw-r--r--docs/api/_templates/.gitkeep0
-rw-r--r--docs/api/apidoc/functest.core.rst3
-rw-r--r--docs/api/apidoc/functest.core.unit.rst7
-rw-r--r--docs/api/apidoc/functest.core.vnf.rst7
-rw-r--r--docs/api/apidoc/functest.core.vnf_base.rst7
-rw-r--r--docs/com/pres/framework/framework.md56
-rw-r--r--docs/testing/developer/internship/unit_tests/index.rst76
-rw-r--r--docs/testing/user/configguide/configguide.rst2
-rw-r--r--functest/ci/config_aarch64_patch.yaml8
-rw-r--r--functest/ci/config_functest.yaml6
-rwxr-xr-xfunctest/ci/run_tests.py405
-rw-r--r--functest/ci/testcases.yaml1
-rw-r--r--functest/ci/tier_builder.py5
-rw-r--r--functest/cli/commands/cli_env.py20
-rw-r--r--functest/cli/commands/cli_os.py18
-rw-r--r--functest/cli/commands/cli_testcase.py13
-rw-r--r--functest/cli/commands/cli_tier.py13
-rw-r--r--functest/core/feature.py2
-rw-r--r--functest/core/pytest_suite_runner.py77
-rw-r--r--functest/core/unit.py84
-rw-r--r--functest/opnfv_tests/openstack/rally/rally.py33
-rwxr-xr-xfunctest/opnfv_tests/openstack/refstack_client/refstack_client.py24
-rwxr-xr-xfunctest/opnfv_tests/openstack/refstack_client/tempest_conf.py8
-rw-r--r--functest/opnfv_tests/openstack/snaps/snaps_test_runner.py4
-rw-r--r--functest/opnfv_tests/openstack/tempest/conf_utils.py138
-rw-r--r--functest/opnfv_tests/openstack/tempest/tempest.py15
-rwxr-xr-xfunctest/opnfv_tests/sdn/odl/odl.py20
-rw-r--r--functest/opnfv_tests/sdn/onos/onos.py8
-rw-r--r--functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py69
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py34
-rw-r--r--functest/tests/unit/ci/test_prepare_env.py3
-rw-r--r--functest/tests/unit/ci/test_run_tests.py174
-rw-r--r--functest/tests/unit/ci/test_tier_builder.py3
-rw-r--r--functest/tests/unit/ci/test_tier_handler.py3
-rw-r--r--functest/tests/unit/cli/commands/test_cli_env.py24
-rw-r--r--functest/tests/unit/cli/commands/test_cli_os.py44
-rw-r--r--functest/tests/unit/cli/commands/test_cli_testcase.py19
-rw-r--r--functest/tests/unit/cli/commands/test_cli_tier.py23
-rw-r--r--functest/tests/unit/cli/test_cli_base.py3
-rw-r--r--functest/tests/unit/core/test_feature.py7
-rw-r--r--functest/tests/unit/core/test_pytest_suite_runner.py51
-rw-r--r--functest/tests/unit/core/test_testcase.py3
-rw-r--r--functest/tests/unit/core/test_unit.py90
-rw-r--r--functest/tests/unit/core/test_vnf.py7
-rw-r--r--functest/tests/unit/energy/test_functest_energy.py3
-rw-r--r--functest/tests/unit/features/test_barometer.py8
-rw-r--r--functest/tests/unit/odl/test_odl.py43
-rw-r--r--functest/tests/unit/openstack/rally/test_rally.py17
-rw-r--r--functest/tests/unit/openstack/refstack_client/test_refstack_client.py26
-rw-r--r--functest/tests/unit/openstack/tempest/test_conf_utils.py39
-rw-r--r--functest/tests/unit/openstack/tempest/test_tempest.py11
-rw-r--r--functest/tests/unit/test_logging.ini27
-rw-r--r--functest/tests/unit/utils/test_decorators.py6
-rw-r--r--functest/tests/unit/utils/test_functest_utils.py16
-rw-r--r--functest/tests/unit/utils/test_openstack_clean.py3
-rw-r--r--functest/tests/unit/utils/test_openstack_snapshot.py3
-rw-r--r--functest/tests/unit/utils/test_openstack_tacker.py3
-rw-r--r--functest/tests/unit/utils/test_openstack_utils.py3
-rw-r--r--functest/tests/unit/vnf/ims/test_clearwater.py3
-rw-r--r--functest/tests/unit/vnf/ims/test_cloudify_ims.py3
-rw-r--r--functest/tests/unit/vnf/ims/test_ims_base.py3
-rw-r--r--functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py3
-rw-r--r--functest/utils/env.py4
-rw-r--r--functest/utils/functest_utils.py8
-rw-r--r--functest/utils/openstack_utils.py8
-rw-r--r--requirements.py3.txt39
-rw-r--r--requirements.txt4
-rwxr-xr-xrun_unit_tests.sh49
-rw-r--r--test-requirements.txt3
-rw-r--r--tox.ini43
74 files changed, 1092 insertions, 918 deletions
diff --git a/.gitignore b/.gitignore
index d8ba0a976..341cf2811 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@ coverage.xml
nosetests.xml
functest.egg-info
*venv
+.tox
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 202eb5cb3..ef5967f7f 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -29,7 +29,6 @@ ARG FUNCTEST_IMAGES_DIR=${FUNCTEST_BASE_DIR}/images
ARG FUNCTEST_RESULTS_DIR=${FUNCTEST_BASE_DIR}/results
ARG FUNCTEST_REPO_DIR=${REPOS_DIR}/functest
ARG FUNCTEST_TEST_DIR=${FUNCTEST_REPO_DIR}/functest/opnfv_tests
-ARG RELENG_MODULE_DIR=${REPOS_DIR}/releng/modules
ARG REPOS_VNFS_DIR=${REPOS_DIR}/vnfs
# Environment variables
@@ -90,11 +89,9 @@ RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/doctor ${REPO
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/promise ${REPOS_DIR}/promise
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/netready ${REPOS_DIR}/netready
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/fds ${REPOS_DIR}/fds
-RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/barometer ${REPOS_DIR}/barometer
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/sfc ${REPOS_DIR}/sfc
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/snaps ${REPOS_DIR}/snaps
RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/securityscanning ${REPOS_DIR}/securityscanning
-RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng ${REPOS_DIR}/releng
RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/opera ${REPOS_DIR}/opera
# OpenStack repositories
@@ -117,12 +114,6 @@ RUN cd ${FUNCTEST_REPO_DIR} \
&& pip install -r requirements.txt \
&& pip install -e .
-RUN cd ${RELENG_MODULE_DIR} \
- && pip install -e .
-
-RUN cd ${REPOS_DIR}/barometer \
- && pip install .
-
RUN pip install ${REPOS_DIR}/opera
RUN find ${FUNCTEST_REPO_DIR} -name "*.py" \
diff --git a/docker/Dockerfile.aarch64 b/docker/Dockerfile.aarch64
index b03c6d978..e323cb18a 100644
--- a/docker/Dockerfile.aarch64
+++ b/docker/Dockerfile.aarch64
@@ -28,7 +28,6 @@ ARG FUNCTEST_IMAGES_DIR=${FUNCTEST_BASE_DIR}/images
ARG FUNCTEST_RESULTS_DIR=${FUNCTEST_BASE_DIR}/results
ARG FUNCTEST_REPO_DIR=${REPOS_DIR}/functest
ARG FUNCTEST_TEST_DIR=${FUNCTEST_REPO_DIR}/functest/opnfv_tests
-ARG RELENG_MODULE_DIR=${REPOS_DIR}/releng/modules
ARG REPOS_VNFS_DIR=${REPOS_DIR}/vnfs
# Environment variables
@@ -90,7 +89,6 @@ RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/promise ${REP
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/sfc ${REPOS_DIR}/sfc
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/snaps ${REPOS_DIR}/snaps
RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/securityscanning ${REPOS_DIR}/securityscanning
-RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng ${REPOS_DIR}/releng
RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/opera ${REPOS_DIR}/opera
# OpenStack repositories
@@ -112,9 +110,6 @@ RUN cd ${FUNCTEST_REPO_DIR} \
&& pip install -r requirements.txt \
&& pip install -e .
-RUN cd ${RELENG_MODULE_DIR} \
- && pip install -e .
-
RUN find ${FUNCTEST_REPO_DIR} -name "*.py" \
-not -path "*tests/unit*" \
-not -path "*functest_venv*" \
diff --git a/docs/api/_static/.gitkeep b/docs/api/_static/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/api/_static/.gitkeep
diff --git a/docs/api/_templates/.gitkeep b/docs/api/_templates/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/api/_templates/.gitkeep
diff --git a/docs/api/apidoc/functest.core.rst b/docs/api/apidoc/functest.core.rst
index 29c67e4e3..55c795be0 100644
--- a/docs/api/apidoc/functest.core.rst
+++ b/docs/api/apidoc/functest.core.rst
@@ -13,5 +13,6 @@ Submodules
functest.core.feature
functest.core.testcase
- functest.core.vnf_base
+ functest.core.vnf
+ functest.core.unit
diff --git a/docs/api/apidoc/functest.core.unit.rst b/docs/api/apidoc/functest.core.unit.rst
new file mode 100644
index 000000000..5dd6880ed
--- /dev/null
+++ b/docs/api/apidoc/functest.core.unit.rst
@@ -0,0 +1,7 @@
+functest.core.unit module
+=========================
+
+.. automodule:: functest.core.unit
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/api/apidoc/functest.core.vnf.rst b/docs/api/apidoc/functest.core.vnf.rst
new file mode 100644
index 000000000..9fd6b375c
--- /dev/null
+++ b/docs/api/apidoc/functest.core.vnf.rst
@@ -0,0 +1,7 @@
+functest.core.vnf module
+========================
+
+.. automodule:: functest.core.vnf
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/api/apidoc/functest.core.vnf_base.rst b/docs/api/apidoc/functest.core.vnf_base.rst
deleted file mode 100644
index 94b2eaa90..000000000
--- a/docs/api/apidoc/functest.core.vnf_base.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-functest.core.vnf_base module
-=============================
-
-.. automodule:: functest.core.vnf_base
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/docs/com/pres/framework/framework.md b/docs/com/pres/framework/framework.md
index 3c1aae1b8..1b07a8e0b 100644
--- a/docs/com/pres/framework/framework.md
+++ b/docs/com/pres/framework/framework.md
@@ -252,6 +252,62 @@ run:
+## class Suite
+bases: TestCase
+
+base model for running unittest.TestSuite
+
+
+### run(**kwargs)
+
+- allows running any unittest.TestSuite
+- sets the following attributes required to push the results to DB:
+ - result
+ - start_time
+ - stop_time
+ - details
+
+
+
+## Your fourth test case
+
+
+### fourth.py
+
+```python
+#!/usr/bin/env python
+
+import unittest
+
+class TestStringMethods(unittest.TestCase):
+
+ def test_upper(self):
+ self.assertEqual('Hello World'.upper(),
+ 'HELLO WORLD')
+```
+
+
+### functest/ci/testcases.yaml
+
+```
+case_name: fourth
+project_name: functest
+criteria: 100
+blocking: true
+clean_flag: false
+description: ''
+dependencies:
+ installer: ''
+ scenario: ''
+run:
+ module: 'functest.core.unit'
+ class: 'Suite'
+ args:
+ name: 'fourth'
+```
+
+
+
## Euphrates
diff --git a/docs/testing/developer/internship/unit_tests/index.rst b/docs/testing/developer/internship/unit_tests/index.rst
index f969aa72d..a117c8609 100644
--- a/docs/testing/developer/internship/unit_tests/index.rst
+++ b/docs/testing/developer/internship/unit_tests/index.rst
@@ -25,41 +25,98 @@ Version history
| **Date** | **Ver.** | **Author** | **Comment** |
| | | | |
+------------+----------+------------------+------------------------+
-| 2016-??-?? | 0.0.1 | Morgan Richomme | Beginning of the |
+| 2016-11-14 | 0.0.1 | Morgan Richomme | Beginning of the |
| | | (Orange) | Internship |
+------------+----------+------------------+------------------------+
+| 2017-03-31 | 0.0.2 | Ashish Kumar | During the |
+| | | (IIIT Hyderabad) | Internship |
++------------+----------+------------------+------------------------+
Overview:
=========
-
+Functest project is developing and integrating functional test cases for OPNFV
+and it is part of OPNFV since the beginning. Functest develops its own testcases
+and framework. This framework includes several utility libraries. The Project is
+growing rapidly with more features, tests added as per requirement. It becomes
+the responsibility of every developer to maintain the integrity of code i.e. new
+patch should not break the previous functionality of the project. To automate this
+process of software development, we should write unit tests and add them to CI so
+that when a new patch is ready to merge, we shouldn't allow those which are breaking
+previous unit tests or decreasing the coverage.
Problem Statement:
------------------
-
+The goal of the intership consists in creating unit test suites on Functest code
+with good code coverage (>80%) and integrate it in continuous integration in order
+to consolidate existing code.
Curation Phase
--------------
+The curation phase was the first 3 to 4 weeks of the internship. This phase was to get
+familiar with the functest code and functionality and explore the solutions for unit
+testing in other projects and come up with the strategy for writing unit tests in functest.
-
+In this phase we decided,
+- Coverage should be 80%. There are some functions like __init__, getter, setter and other
+ private methods for which writing unit test is a tedious job, so we are leaving these methods
+ for now.
+- Do method wise testing for every module.
+- Use mock for external or third party services, system calls and other external library calls
+ which could impact the behaviour of system during the run of unit test.
+- Add it in jenkins as passing criteria for patches.
+- Write tests in modular way so that it can help to serve as a form of documentation.
Schedule:
=========
-
-
-
+--------------------------+------------------------------------------+
| **Date** | **Comment** |
| | |
+--------------------------+------------------------------------------+
-| December - January | ........ |
+| Nov 14th - Nov 28th | 1. Learn Functest Project Business |
+| | 2. Set up the development environment |
+| | 3. Run Functest code |
++--------------------------+------------------------------------------+
+| Nov 28th - Dec.9th | 1. Explore Unit Testing Strategy, |
+| | 2. Learn about Mock in python |
++--------------------------+------------------------------------------+
+| Dec 12th - Dec 23rd | Implement Unit Tests for CLI |
+| | |
++--------------------------+------------------------------------------+
+| Dec 26th - Jan 6th | Implement Unit Tests for Utils |
+| | |
++--------------------------+------------------------------------------+
+| Jan 9th - Jan 20th | Implement Unit Tests for CI |
+| | |
++--------------------------+------------------------------------------+
+| Jan 23rd - Feb 3rd | Implement Unit Tests for Core |
+| | |
++--------------------------+------------------------------------------+
+| Feb 6th - Feb 17th | Implement Unit Tests for |
+| | opnfv_tests/openstack/tempest |
+--------------------------+------------------------------------------+
-| January - february | ........ |
+| Feb 20th - Mar 3rd | Implement Unit Tests for |
+| | opnfv_tests/openstack/rally |
++--------------------------+------------------------------------------+
+| Mar 6th - Mar 17th | Implement Unit Tests for |
+| | opnfv_tests/vnf/ims |
++--------------------------+------------------------------------------+
+| Mar 20th - Mar 31st | Recheck and Increase Coverage for all |
+| | modules > 80% |
++--------------------------+------------------------------------------+
+| Apr 3rd - Apr 14th | Add CI Gating for unit tests |
+| | |
++--------------------------+------------------------------------------+
+| Apr 17th - Apr 28th | Use Tox Utility, Documentation |
+| | |
++--------------------------+------------------------------------------+
+| Apr 28th - End | Bug Fixing |
+| | |
+--------------------------+------------------------------------------+
@@ -67,4 +124,3 @@ References:
===========
.. _`[1]` : https://wiki.opnfv.org/display/DEV/Intern+Project%3A+Functest+unit+tests
-
diff --git a/docs/testing/user/configguide/configguide.rst b/docs/testing/user/configguide/configguide.rst
index 9a1749789..12dfd1059 100644
--- a/docs/testing/user/configguide/configguide.rst
+++ b/docs/testing/user/configguide/configguide.rst
@@ -74,7 +74,7 @@ executing the following sequence
#. Log in to container and execute the following command. Replace
the IP with installer address after the "-a" parameter::
- $REPOS_DIR/releng/utils/fetch_os_creds.sh \
+ fetch_os_creds.sh \
-d /home/opnfv/functest/conf/openstack.creds \
-i fuel \
-a 10.20.0.2 \
diff --git a/functest/ci/config_aarch64_patch.yaml b/functest/ci/config_aarch64_patch.yaml
index b43b5a76c..cd395ab89 100644
--- a/functest/ci/config_aarch64_patch.yaml
+++ b/functest/ci/config_aarch64_patch.yaml
@@ -16,5 +16,13 @@ os:
vping:
image_name: TestVM
+ odl_sfc:
+ image_base_url: "http://artifacts.opnfv.org/sfc/demo"
+ image_name: sfc_nsh_danube
+ image_file_name: sf_nsh_danube_arm64.img
+ image_initrd: sf_nsh_danube_arm64-initrd
+ image_kernel: sf_nsh_danube_arm64-kernel
+ image_format: ami
+ os_cmd_line: 'root=LABEL=cloudimg-rootfs ro'
doctor:
image_name: TestVM
diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml
index 5496dd946..9b7960718 100644
--- a/functest/ci/config_functest.yaml
+++ b/functest/ci/config_functest.yaml
@@ -118,6 +118,12 @@ onos_sfc:
image_name: TestSfcVm
image_file_name: firewall_block_image.img
+odl_sfc:
+ image_base_url: "http://artifacts.opnfv.org/sfc/images"
+ image_name: sfc_nsh_danube
+ image_file_name: sfc_nsh_danube.qcow2
+ image_format: qcow2
+
tempest:
deployment_name: opnfv-tempest
identity:
diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py
index 76760096b..8317df541 100755
--- a/functest/ci/run_tests.py
+++ b/functest/ci/run_tests.py
@@ -64,210 +64,210 @@ class RunTestsParser(object):
return vars(self.parser.parse_args(argv))
-class GlobalVariables:
- EXECUTED_TEST_CASES = []
- OVERALL_RESULT = Result.EX_OK
- CLEAN_FLAG = True
- REPORT_FLAG = False
-
-
-def print_separator(str, count=45):
- line = ""
- for i in range(0, count - 1):
- line += str
- logger.info("%s" % line)
-
-
-def source_rc_file():
- rc_file = CONST.__getattribute__('openstack_creds')
- if not os.path.isfile(rc_file):
- raise Exception("RC file %s does not exist..." % rc_file)
- logger.debug("Sourcing the OpenStack RC file...")
- os_utils.source_credentials(rc_file)
- for key, value in os.environ.iteritems():
- if re.search("OS_", key):
- if key == 'OS_AUTH_URL':
- CONST.__setattr__('OS_AUTH_URL', value)
- elif key == 'OS_USERNAME':
- CONST.__setattr__('OS_USERNAME', value)
- elif key == 'OS_TENANT_NAME':
- CONST.__setattr__('OS_TENANT_NAME', value)
- elif key == 'OS_PASSWORD':
- CONST.__setattr__('OS_PASSWORD', value)
-
-
-def generate_os_snapshot():
- os_snapshot.main()
-
-
-def cleanup():
- os_clean.main()
-
-
-def get_run_dict(testname):
- try:
- dict = ft_utils.get_dict_by_test(testname)
- if not dict:
- logger.error("Cannot get {}'s config options".format(testname))
- elif 'run' in dict:
- return dict['run']
- return None
- except Exception:
- logger.exception("Cannot get {}'s config options".format(testname))
- return None
-
-
-def run_test(test, tier_name, testcases=None):
- if not test.is_enabled():
- raise TestNotEnabled("The test case {} is not enabled"
- .format(test.get_name()))
- test_name = test.get_name()
- logger.info("\n") # blank line
- print_separator("=")
- logger.info("Running test case '%s'..." % test_name)
- print_separator("=")
- logger.debug("\n%s" % test)
- source_rc_file()
-
- if test.needs_clean() and GlobalVariables.CLEAN_FLAG:
- generate_os_snapshot()
-
- flags = (" -t %s" % (test_name))
- if GlobalVariables.REPORT_FLAG:
- flags += " -r"
-
- result = testcase.TestCase.EX_RUN_ERROR
- run_dict = get_run_dict(test_name)
- if run_dict:
+class Runner(object):
+
+ def __init__(self):
+ self.executed_test_cases = []
+ self.overall_result = Result.EX_OK
+ self.clean_flag = True
+ self.report_flag = False
+
+ @staticmethod
+ def print_separator(str, count=45):
+ line = ""
+ for i in range(0, count - 1):
+ line += str
+ logger.info("%s" % line)
+
+ @staticmethod
+ def source_rc_file():
+ rc_file = CONST.__getattribute__('openstack_creds')
+ if not os.path.isfile(rc_file):
+ raise Exception("RC file %s does not exist..." % rc_file)
+ logger.debug("Sourcing the OpenStack RC file...")
+ os_utils.source_credentials(rc_file)
+ for key, value in os.environ.iteritems():
+ if re.search("OS_", key):
+ if key == 'OS_AUTH_URL':
+ CONST.__setattr__('OS_AUTH_URL', value)
+ elif key == 'OS_USERNAME':
+ CONST.__setattr__('OS_USERNAME', value)
+ elif key == 'OS_TENANT_NAME':
+ CONST.__setattr__('OS_TENANT_NAME', value)
+ elif key == 'OS_PASSWORD':
+ CONST.__setattr__('OS_PASSWORD', value)
+
+ @staticmethod
+ def generate_os_snapshot():
+ os_snapshot.main()
+
+ @staticmethod
+ def cleanup():
+ os_clean.main()
+
+ @staticmethod
+ def get_run_dict(testname):
try:
- module = importlib.import_module(run_dict['module'])
- cls = getattr(module, run_dict['class'])
- test_dict = ft_utils.get_dict_by_test(test_name)
- test_case = cls(**test_dict)
- GlobalVariables.EXECUTED_TEST_CASES.append(test_case)
+ dict = ft_utils.get_dict_by_test(testname)
+ if not dict:
+ logger.error("Cannot get {}'s config options".format(testname))
+ elif 'run' in dict:
+ return dict['run']
+ return None
+ except Exception:
+ logger.exception("Cannot get {}'s config options".format(testname))
+ return None
+
+ def run_test(self, test, tier_name, testcases=None):
+ if not test.is_enabled():
+ raise TestNotEnabled(
+ "The test case {} is not enabled".format(test.get_name()))
+ logger.info("\n") # blank line
+ self.print_separator("=")
+ logger.info("Running test case '%s'..." % test.get_name())
+ self.print_separator("=")
+ logger.debug("\n%s" % test)
+ self.source_rc_file()
+
+ if test.needs_clean() and self.clean_flag:
+ self.generate_os_snapshot()
+
+ flags = " -t %s" % test.get_name()
+ if self.report_flag:
+ flags += " -r"
+
+ result = testcase.TestCase.EX_RUN_ERROR
+ run_dict = self.get_run_dict(test.get_name())
+ if run_dict:
try:
- kwargs = run_dict['args']
- result = test_case.run(**kwargs)
- except KeyError:
- result = test_case.run()
- if result == testcase.TestCase.EX_OK:
- if GlobalVariables.REPORT_FLAG:
- test_case.push_to_db()
- result = test_case.is_successful()
- logger.info("Test result:\n\n%s\n", test_case)
- except ImportError:
- logger.exception("Cannot import module {}".format(
- run_dict['module']))
- except AttributeError:
- logger.exception("Cannot get class {}".format(
- run_dict['class']))
- else:
- raise Exception("Cannot import the class for the test case.")
-
- if test.needs_clean() and GlobalVariables.CLEAN_FLAG:
- cleanup()
- if result != testcase.TestCase.EX_OK:
- logger.error("The test case '%s' failed. " % test_name)
- GlobalVariables.OVERALL_RESULT = Result.EX_ERROR
- if test.is_blocking():
- raise BlockingTestFailed("The test case {} failed and is blocking"
- .format(test.get_name()))
-
-
-def run_tier(tier):
- tier_name = tier.get_name()
- tests = tier.get_tests()
- if tests is None or len(tests) == 0:
- logger.info("There are no supported test cases in this tier "
- "for the given scenario")
- return 0
- logger.info("\n\n") # blank line
- print_separator("#")
- logger.info("Running tier '%s'" % tier_name)
- print_separator("#")
- logger.debug("\n%s" % tier)
- for test in tests:
- run_test(test, tier_name)
-
-
-def run_all(tiers):
- summary = ""
- tiers_to_run = []
-
- for tier in tiers.get_tiers():
- if (len(tier.get_tests()) != 0 and
- re.search(CONST.__getattribute__('CI_LOOP'),
- tier.get_ci_loop()) is not None):
- tiers_to_run.append(tier)
- summary += ("\n - %s:\n\t %s"
- % (tier.get_name(),
- tier.get_test_names()))
-
- logger.info("Tests to be executed:%s" % summary)
- for tier in tiers_to_run:
- run_tier(tier)
-
-
-def main(**kwargs):
-
- file = CONST.functest_testcases_yaml
- _tiers = tb.TierBuilder(CONST.__getattribute__('INSTALLER_TYPE'),
- CONST.__getattribute__('DEPLOY_SCENARIO'),
- file)
-
- if kwargs['noclean']:
- GlobalVariables.CLEAN_FLAG = False
-
- if kwargs['report']:
- GlobalVariables.REPORT_FLAG = True
-
- try:
- if kwargs['test']:
- source_rc_file()
- if _tiers.get_tier(kwargs['test']):
- run_tier(_tiers.get_tier(kwargs['test']))
- elif _tiers.get_test(kwargs['test']):
- run_test(_tiers.get_test(kwargs['test']),
- _tiers.get_tier_name(kwargs['test']),
- kwargs['test'])
- elif kwargs['test'] == "all":
- run_all(_tiers)
- else:
- logger.error("Unknown test case or tier '%s', "
- "or not supported by "
- "the given scenario '%s'."
- % (kwargs['test'],
- CONST.__getattribute__('DEPLOY_SCENARIO')))
- logger.debug("Available tiers are:\n\n%s"
- % _tiers)
- return Result.EX_ERROR
+ module = importlib.import_module(run_dict['module'])
+ cls = getattr(module, run_dict['class'])
+ test_dict = ft_utils.get_dict_by_test(test.get_name())
+ test_case = cls(**test_dict)
+ self.executed_test_cases.append(test_case)
+ try:
+ kwargs = run_dict['args']
+ result = test_case.run(**kwargs)
+ except KeyError:
+ result = test_case.run()
+ if result == testcase.TestCase.EX_OK:
+ if self.report_flag:
+ test_case.push_to_db()
+ result = test_case.is_successful()
+ logger.info("Test result:\n\n%s\n", test_case)
+ except ImportError:
+ logger.exception("Cannot import module {}".format(
+ run_dict['module']))
+ except AttributeError:
+ logger.exception("Cannot get class {}".format(
+ run_dict['class']))
else:
- run_all(_tiers)
- except Exception as e:
- logger.error(e)
- GlobalVariables.OVERALL_RESULT = Result.EX_ERROR
-
- msg = prettytable.PrettyTable(
- header_style='upper', padding_width=5,
- field_names=['env var', 'value'])
- for env_var in ['INSTALLER_TYPE', 'DEPLOY_SCENARIO', 'BUILD_TAG',
- 'CI_LOOP']:
- msg.add_row([env_var, CONST.__getattribute__(env_var)])
- logger.info("Deployment description: \n\n%s\n", msg)
-
- msg = prettytable.PrettyTable(
- header_style='upper', padding_width=5,
- field_names=['test case', 'project', 'tier', 'duration', 'result'])
- for test_case in GlobalVariables.EXECUTED_TEST_CASES:
- result = 'PASS' if(test_case.is_successful(
- ) == test_case.EX_OK) else 'FAIL'
- msg.add_row([test_case.case_name, test_case.project_name,
- _tiers.get_tier_name(test_case.case_name),
- test_case.get_duration(), result])
- logger.info("FUNCTEST REPORT: \n\n%s\n", msg)
-
- logger.info("Execution exit value: %s" % GlobalVariables.OVERALL_RESULT)
- return GlobalVariables.OVERALL_RESULT
+ raise Exception("Cannot import the class for the test case.")
+
+ if test.needs_clean() and self.clean_flag:
+ self.cleanup()
+ if result != testcase.TestCase.EX_OK:
+ logger.error("The test case '%s' failed. " % test.get_name())
+ self.overall_result = Result.EX_ERROR
+ if test.is_blocking():
+ raise BlockingTestFailed(
+ "The test case {} failed and is blocking".format(
+ test.get_name()))
+
+ def run_tier(self, tier):
+ tier_name = tier.get_name()
+ tests = tier.get_tests()
+ if tests is None or len(tests) == 0:
+ logger.info("There are no supported test cases in this tier "
+ "for the given scenario")
+ return 0
+ logger.info("\n\n") # blank line
+ self.print_separator("#")
+ logger.info("Running tier '%s'" % tier_name)
+ self.print_separator("#")
+ logger.debug("\n%s" % tier)
+ for test in tests:
+ self.run_test(test, tier_name)
+
+ def run_all(self, tiers):
+ summary = ""
+ tiers_to_run = []
+
+ for tier in tiers.get_tiers():
+ if (len(tier.get_tests()) != 0 and
+ re.search(CONST.__getattribute__('CI_LOOP'),
+ tier.get_ci_loop()) is not None):
+ tiers_to_run.append(tier)
+ summary += ("\n - %s:\n\t %s"
+ % (tier.get_name(),
+ tier.get_test_names()))
+
+ logger.info("Tests to be executed:%s" % summary)
+ for tier in tiers_to_run:
+ self.run_tier(tier)
+
+ def main(self, **kwargs):
+ _tiers = tb.TierBuilder(
+ CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ CONST.__getattribute__("functest_testcases_yaml"))
+
+ if kwargs['noclean']:
+ self.clean_flag = False
+
+ if kwargs['report']:
+ self.report_flag = True
+
+ try:
+ if kwargs['test']:
+ self.source_rc_file()
+ logger.debug("Test args: %s", kwargs['test'])
+ if _tiers.get_tier(kwargs['test']):
+ self.run_tier(_tiers.get_tier(kwargs['test']))
+ elif _tiers.get_test(kwargs['test']):
+ self.run_test(_tiers.get_test(kwargs['test']),
+ _tiers.get_tier_name(kwargs['test']),
+ kwargs['test'])
+ elif kwargs['test'] == "all":
+ self.run_all(_tiers)
+ else:
+ logger.error("Unknown test case or tier '%s', "
+ "or not supported by "
+ "the given scenario '%s'."
+ % (kwargs['test'],
+ CONST.__getattribute__('DEPLOY_SCENARIO')))
+ logger.debug("Available tiers are:\n\n%s",
+ _tiers)
+ return Result.EX_ERROR
+ else:
+ self.run_all(_tiers)
+ except BlockingTestFailed:
+ pass
+ except Exception:
+ logger.exception("Failures when running testcase(s)")
+ self.overall_result = Result.EX_ERROR
+
+ msg = prettytable.PrettyTable(
+ header_style='upper', padding_width=5,
+ field_names=['env var', 'value'])
+ for env_var in ['INSTALLER_TYPE', 'DEPLOY_SCENARIO', 'BUILD_TAG',
+ 'CI_LOOP']:
+ msg.add_row([env_var, CONST.__getattribute__(env_var)])
+ logger.info("Deployment description: \n\n%s\n", msg)
+
+ msg = prettytable.PrettyTable(
+ header_style='upper', padding_width=5,
+ field_names=['test case', 'project', 'tier', 'duration', 'result'])
+ for test_case in self.executed_test_cases:
+ result = 'PASS' if(test_case.is_successful(
+ ) == test_case.EX_OK) else 'FAIL'
+ msg.add_row([test_case.case_name, test_case.project_name,
+ _tiers.get_tier_name(test_case.case_name),
+ test_case.get_duration(), result])
+ logger.info("FUNCTEST REPORT: \n\n%s\n", msg)
+
+ logger.info("Execution exit value: %s" % self.overall_result)
+ return self.overall_result
if __name__ == '__main__':
@@ -275,4 +275,5 @@ if __name__ == '__main__':
CONST.__getattribute__('dir_functest_logging_cfg'))
parser = RunTestsParser()
args = parser.parse_args(sys.argv[1:])
- sys.exit(main(**args).value)
+ runner = Runner()
+ sys.exit(runner.main(**args).value)
diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml
index 504f00ed4..8222df102 100644
--- a/functest/ci/testcases.yaml
+++ b/functest/ci/testcases.yaml
@@ -301,7 +301,6 @@ tiers:
-
case_name: bgpvpn
- enabled: false
project_name: sdnvpn
criteria: 100
blocking: false
diff --git a/functest/ci/tier_builder.py b/functest/ci/tier_builder.py
index 12562f09c..d03cd9032 100644
--- a/functest/ci/tier_builder.py
+++ b/functest/ci/tier_builder.py
@@ -54,8 +54,9 @@ class TierBuilder(object):
blocking=dic_testcase['blocking'],
clean_flag=dic_testcase['clean_flag'],
description=dic_testcase['description'])
- if (testcase.is_compatible(self.ci_installer, self.ci_scenario)
- and testcase.is_enabled()):
+ if (testcase.is_compatible(self.ci_installer,
+ self.ci_scenario) and
+ testcase.is_enabled()):
tier.add_test(testcase)
self.tier_objects.append(tier)
diff --git a/functest/cli/commands/cli_env.py b/functest/cli/commands/cli_env.py
index 14ad01bfc..f5ba4b342 100644
--- a/functest/cli/commands/cli_env.py
+++ b/functest/cli/commands/cli_env.py
@@ -28,7 +28,7 @@ class CliEnv(object):
"it again? [y|n]\n")
while True:
if answer.lower() in ["y", "yes"]:
- os.remove(CONST.env_active)
+ os.remove(CONST.__getattribute__('env_active'))
break
elif answer.lower() in ["n", "no"]:
return
@@ -36,19 +36,19 @@ class CliEnv(object):
answer = raw_input("Invalid answer. Please type [y|n]\n")
cmd = ("python %s/functest/ci/prepare_env.py start" %
- CONST.dir_repo_functest)
+ CONST.__getattribute__('dir_repo_functest'))
ft_utils.execute_command(cmd)
def show(self):
def _get_value(attr, default='Unknown'):
return attr if attr else default
- install_type = _get_value(CONST.INSTALLER_TYPE)
- installer_ip = _get_value(CONST.INSTALLER_IP)
+ install_type = _get_value(CONST.__getattribute__('INSTALLER_TYPE'))
+ installer_ip = _get_value(CONST.__getattribute__('INSTALLER_IP'))
installer_info = ("%s, %s" % (install_type, installer_ip))
- scenario = _get_value(CONST.DEPLOY_SCENARIO)
- node = _get_value(CONST.NODE_NAME)
- repo_h = git.Repo(CONST.dir_repo_functest).head
+ scenario = _get_value(CONST.__getattribute__('DEPLOY_SCENARIO'))
+ node = _get_value(CONST.__getattribute__('NODE_NAME'))
+ repo_h = git.Repo(CONST.__getattribute__('dir_repo_functest')).head
if repo_h.is_detached:
git_branch = 'detached from FETCH_HEAD'
git_hash = repo_h.commit.hexsha
@@ -56,8 +56,8 @@ class CliEnv(object):
branch = repo_h.reference
git_branch = branch.name
git_hash = branch.commit.hexsha
- is_debug = _get_value(CONST.CI_DEBUG, 'false')
- build_tag = CONST.BUILD_TAG
+ is_debug = _get_value(CONST.__getattribute__('CI_DEBUG'), 'false')
+ build_tag = CONST.__getattribute__('BUILD_TAG')
if build_tag is not None:
build_tag = build_tag.lstrip(
"jenkins-").lstrip("functest").lstrip("-")
@@ -84,7 +84,7 @@ class CliEnv(object):
def status(self, verbose=True):
ret_val = 0
- if not os.path.isfile(CONST.env_active):
+ if not os.path.isfile(CONST.__getattribute__('env_active')):
if verbose:
click.echo("Functest environment is not installed.\n")
ret_val = 1
diff --git a/functest/cli/commands/cli_os.py b/functest/cli/commands/cli_os.py
index f85f4041f..5e6e1109a 100644
--- a/functest/cli/commands/cli_os.py
+++ b/functest/cli/commands/cli_os.py
@@ -21,11 +21,11 @@ import functest.utils.openstack_snapshot as os_snapshot
class CliOpenStack(object):
def __init__(self):
- self.os_auth_url = CONST.OS_AUTH_URL
+ self.os_auth_url = CONST.__getattribute__('OS_AUTH_URL')
self.endpoint_ip = None
self.endpoint_port = None
- self.openstack_creds = CONST.openstack_creds
- self.snapshot_file = CONST.openstack_snapshot_file
+ self.openstack_creds = CONST.__getattribute__('openstack_creds')
+ self.snapshot_file = CONST.__getattribute__('openstack_snapshot_file')
if self.os_auth_url:
self.endpoint_ip = self.os_auth_url.rsplit("/")[2].rsplit(":")[0]
self.endpoint_port = self.os_auth_url.rsplit("/")[2].rsplit(":")[1]
@@ -59,17 +59,16 @@ class CliOpenStack(object):
else:
answer = raw_input("Invalid answer. Please type [y|n]\n")
- installer_type = CONST.INSTALLER_TYPE
+ installer_type = CONST.__getattribute__('INSTALLER_TYPE')
if installer_type is None:
click.echo("The environment variable 'INSTALLER_TYPE' is not"
"defined. Please export it")
- installer_ip = CONST.INSTALLER_IP
+ installer_ip = CONST.__getattribute__('INSTALLER_IP')
if installer_ip is None:
click.echo("The environment variable 'INSTALLER_IP' is not"
"defined. Please export it")
- cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
- self.openstack_creds,
+ cmd = ("fetch_os_creds.sh -d %s -i %s -a %s"
+ % (self.openstack_creds,
installer_type,
installer_ip))
click.echo("Fetching credentials from installer node '%s' with IP=%s.."
@@ -78,7 +77,8 @@ class CliOpenStack(object):
def check(self):
self.ping_endpoint()
- cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh"
+ cmd = os.path.join(CONST.__getattribute__('dir_repo_functest'),
+ "functest/ci/check_os.sh")
ft_utils.execute_command(cmd, verbose=False)
def snapshot_create(self):
diff --git a/functest/cli/commands/cli_testcase.py b/functest/cli/commands/cli_testcase.py
index 6644a0c29..3d3f1cb3e 100644
--- a/functest/cli/commands/cli_testcase.py
+++ b/functest/cli/commands/cli_testcase.py
@@ -22,9 +22,10 @@ import functest.utils.functest_vacation as vacation
class CliTestcase(object):
def __init__(self):
- self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE,
- CONST.DEPLOY_SCENARIO,
- CONST.functest_testcases_yaml)
+ self.tiers = tb.TierBuilder(
+ CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ CONST.__getattribute__('functest_testcases_yaml'))
def list(self):
summary = ""
@@ -52,12 +53,14 @@ class CliTestcase(object):
if testname == 'vacation':
vacation.main()
- elif not os.path.isfile(CONST.env_active):
+ elif not os.path.isfile(CONST.__getattribute__('env_active')):
click.echo("Functest environment is not ready. "
"Run first 'functest env prepare'")
else:
tests = testname.split(",")
for test in tests:
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, flags, test))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ flags, test))
ft_utils.execute_command(cmd)
diff --git a/functest/cli/commands/cli_tier.py b/functest/cli/commands/cli_tier.py
index 012b11d0e..531f0ff96 100644
--- a/functest/cli/commands/cli_tier.py
+++ b/functest/cli/commands/cli_tier.py
@@ -21,9 +21,10 @@ import functest.utils.functest_utils as ft_utils
class CliTier(object):
def __init__(self):
- self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE,
- CONST.DEPLOY_SCENARIO,
- CONST.functest_testcases_yaml)
+ self.tiers = tb.TierBuilder(
+ CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ CONST.__getattribute__('functest_testcases_yaml'))
def list(self):
summary = ""
@@ -62,10 +63,12 @@ class CliTier(object):
if report:
flags += "-r "
- if not os.path.isfile(CONST.env_active):
+ if not os.path.isfile(CONST.__getattribute__('env_active')):
click.echo("Functest environment is not ready. "
"Run first 'functest env prepare'")
else:
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, flags, tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ flags, tiername))
ft_utils.execute_command(cmd)
diff --git a/functest/core/feature.py b/functest/core/feature.py
index 140c9bb2e..d53eb7d0e 100644
--- a/functest/core/feature.py
+++ b/functest/core/feature.py
@@ -7,7 +7,7 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
-"""Define the parent class of all Functest Features.
+"""Define the parent classes of all Functest Features.
Feature is considered as TestCase offered by Third-party. It offers
helpers to run any python method or any bash command.
diff --git a/functest/core/pytest_suite_runner.py b/functest/core/pytest_suite_runner.py
deleted file mode 100644
index a6e476600..000000000
--- a/functest/core/pytest_suite_runner.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright (c) 2015 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 time
-import unittest
-
-import six
-
-from functest.core import testcase
-
-
-class PyTestSuiteRunner(testcase.TestCase):
- """
- This superclass is designed to execute pre-configured unittest.TestSuite()
- objects
- """
-
- def __init__(self, **kwargs):
- super(PyTestSuiteRunner, self).__init__(**kwargs)
- self.suite = None
- self.logger = logging.getLogger(__name__)
-
- def run(self, **kwargs):
- """
- Starts test execution from the functest framework
- """
- try:
- name = kwargs["name"]
- try:
- self.suite = unittest.TestLoader().loadTestsFromName(name)
- except ImportError:
- self.logger.error("Can not import %s", name)
- return testcase.TestCase.EX_RUN_ERROR
- except KeyError:
- pass
- self.start_time = time.time()
- stream = six.StringIO()
- result = unittest.TextTestRunner(
- stream=stream, verbosity=2).run(self.suite)
- self.logger.debug("\n\n%s", stream.getvalue())
- self.stop_time = time.time()
-
- if result.errors:
- self.logger.error('Number of errors in test suite - ' +
- str(len(result.errors)))
- for test, message in result.errors:
- self.logger.error(str(test) + " ERROR with " + message)
-
- if result.failures:
- self.logger.error('Number of failures in test suite - ' +
- str(len(result.failures)))
- for test, message in result.failures:
- self.logger.error(str(test) + " FAILED with " + message)
-
- # a result can be PASS or FAIL
- # But in this case it means that the Execution was OK
- # we shall distinguish Execution Error from FAIL results
- # TestCase.EX_RUN_ERROR means that the test case was not run
- # not that it was run but the result was FAIL
- exit_code = testcase.TestCase.EX_OK
- if ((result.errors and len(result.errors) > 0) or
- (result.failures and len(result.failures) > 0)):
- self.logger.info("%s FAILED", self.case_name)
- self.result = 0
- else:
- self.logger.info("%s OK", self.case_name)
- self.result = 100
-
- self.details = {}
- return exit_code
diff --git a/functest/core/unit.py b/functest/core/unit.py
new file mode 100644
index 000000000..6799420c7
--- /dev/null
+++ b/functest/core/unit.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 Cable Television Laboratories, Inc. 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 parent class to run unittest.TestSuite as TestCase."""
+
+from __future__ import division
+
+import logging
+import time
+import unittest
+
+import six
+
+from functest.core import testcase
+
+__author__ = ("Steven Pisarski <s.pisarski@cablelabs.com>, "
+ "Cedric Ollivier <cedric.ollivier@orange.com>")
+
+
+class Suite(testcase.TestCase):
+ """Base model for running unittest.TestSuite."""
+
+ def __init__(self, **kwargs):
+ super(Suite, self).__init__(**kwargs)
+ self.suite = None
+ self.logger = logging.getLogger(__name__)
+
+ def run(self, **kwargs):
+ """Run the test suite.
+
+ It allows running any unittest.TestSuite and getting its
+ execution status.
+
+ By default, it runs the suite defined as instance attribute.
+ It can be overriden by passing name as arg. It must
+ conform with TestLoader.loadTestsFromName().
+
+ It sets the following attributes required to push the results
+ to DB:
+
+ * result,
+ * start_time,
+ * stop_time,
+ * details.
+
+ Args:
+ kwargs: Arbitrary keyword arguments.
+
+ Returns:
+ TestCase.EX_OK if any TestSuite has been run,
+ TestCase.EX_RUN_ERROR otherwise.
+ """
+ try:
+ name = kwargs["name"]
+ try:
+ self.suite = unittest.TestLoader().loadTestsFromName(name)
+ except ImportError:
+ self.logger.error("Can not import %s", name)
+ return testcase.TestCase.EX_RUN_ERROR
+ except KeyError:
+ pass
+ self.start_time = time.time()
+ stream = six.StringIO()
+ result = unittest.TextTestRunner(
+ stream=stream, verbosity=2).run(self.suite)
+ self.logger.debug("\n\n%s", stream.getvalue())
+ self.stop_time = time.time()
+ self.details = {"failures": result.failures,
+ "errors": result.errors}
+ try:
+ self.result = 100 * (
+ (result.testsRun - (len(result.failures) +
+ len(result.errors))) /
+ result.testsRun)
+ return testcase.TestCase.EX_OK
+ except ZeroDivisionError:
+ self.logger.error("No test has been run")
+ return testcase.TestCase.EX_RUN_ERROR
diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py
index 40f8386c8..86ec35584 100644
--- a/functest/opnfv_tests/openstack/rally/rally.py
+++ b/functest/opnfv_tests/openstack/rally/rally.py
@@ -30,14 +30,17 @@ logger = logging.getLogger(__name__)
class RallyBase(testcase.TestCase):
TESTS = ['authenticate', 'glance', 'cinder', 'heat', 'keystone',
'neutron', 'nova', 'quotas', 'requests', 'vm', 'all']
- GLANCE_IMAGE_NAME = CONST.openstack_image_name
- GLANCE_IMAGE_FILENAME = CONST.openstack_image_file_name
- GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_images,
- GLANCE_IMAGE_FILENAME)
- GLANCE_IMAGE_FORMAT = CONST.openstack_image_disk_format
+ GLANCE_IMAGE_NAME = CONST.__getattribute__('openstack_image_name')
+ GLANCE_IMAGE_FILENAME = CONST.__getattribute__('openstack_image_file_name')
+ GLANCE_IMAGE_PATH = os.path.join(
+ CONST.__getattribute__('dir_functest_images'),
+ GLANCE_IMAGE_FILENAME)
+ GLANCE_IMAGE_FORMAT = CONST.__getattribute__('openstack_image_disk_format')
FLAVOR_NAME = "m1.tiny"
- RALLY_DIR = os.path.join(CONST.dir_repo_functest, CONST.dir_rally)
+ RALLY_DIR = os.path.join(
+ CONST.__getattribute__('dir_repo_functest'),
+ CONST.__getattribute__('dir_rally'))
RALLY_SCENARIO_DIR = os.path.join(RALLY_DIR, "scenario")
TEMPLATE_DIR = os.path.join(RALLY_SCENARIO_DIR, "templates")
SUPPORT_DIR = os.path.join(RALLY_SCENARIO_DIR, "support")
@@ -45,17 +48,17 @@ class RallyBase(testcase.TestCase):
TENANTS_AMOUNT = 3
ITERATIONS_AMOUNT = 10
CONCURRENCY = 4
- RESULTS_DIR = os.path.join(CONST.dir_results, 'rally')
- TEMPEST_CONF_FILE = os.path.join(CONST.dir_results,
+ RESULTS_DIR = os.path.join(CONST.__getattribute__('dir_results'), 'rally')
+ TEMPEST_CONF_FILE = os.path.join(CONST.__getattribute__('dir_results'),
'tempest/tempest.conf')
BLACKLIST_FILE = os.path.join(RALLY_DIR, "blacklist.txt")
TEMP_DIR = os.path.join(RALLY_DIR, "var")
CINDER_VOLUME_TYPE_NAME = "volume_test"
- RALLY_PRIVATE_NET_NAME = CONST.rally_network_name
- RALLY_PRIVATE_SUBNET_NAME = CONST.rally_subnet_name
- RALLY_PRIVATE_SUBNET_CIDR = CONST.rally_subnet_cidr
- RALLY_ROUTER_NAME = CONST.rally_router_name
+ RALLY_PRIVATE_NET_NAME = CONST.__getattribute__('rally_network_name')
+ RALLY_PRIVATE_SUBNET_NAME = CONST.__getattribute__('rally_subnet_name')
+ RALLY_PRIVATE_SUBNET_CIDR = CONST.__getattribute__('rally_subnet_cidr')
+ RALLY_ROUTER_NAME = CONST.__getattribute__('rally_router_name')
def __init__(self, **kwargs):
super(RallyBase, self).__init__(**kwargs)
@@ -97,7 +100,7 @@ class RallyBase(testcase.TestCase):
task_args['netid'] = ''
# get keystone auth endpoint
- task_args['request_url'] = CONST.OS_AUTH_URL or ''
+ task_args['request_url'] = CONST.__getattribute__('OS_AUTH_URL') or ''
return task_args
@@ -183,8 +186,8 @@ class RallyBase(testcase.TestCase):
with open(RallyBase.BLACKLIST_FILE, 'r') as black_list_file:
black_list_yaml = yaml.safe_load(black_list_file)
- installer_type = CONST.INSTALLER_TYPE
- deploy_scenario = CONST.DEPLOY_SCENARIO
+ installer_type = CONST.__getattribute__('INSTALLER_TYPE')
+ deploy_scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
if (bool(installer_type) * bool(deploy_scenario)):
if 'scenario' in black_list_yaml.keys():
for item in black_list_yaml['scenario']:
diff --git a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
index 2a2718dd8..5f1f3a1dd 100755
--- a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
+++ b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
@@ -33,9 +33,9 @@ class RefstackClient(testcase.TestCase):
if "case_name" not in kwargs:
kwargs["case_name"] = "refstack_defcore"
super(RefstackClient, self).__init__(**kwargs)
- self.FUNCTEST_TEST = CONST.dir_functest_test
- self.CONF_PATH = CONST.refstack_tempest_conf_path
- self.DEFCORE_LIST = CONST.refstack_defcore_list
+ self.FUNCTEST_TEST = CONST.__getattribute__('dir_functest_test')
+ self.CONF_PATH = CONST.__getattribute__('refstack_tempest_conf_path')
+ self.DEFCORE_LIST = CONST.__getattribute__('refstack_defcore_list')
self.confpath = os.path.join(self.FUNCTEST_TEST,
self.CONF_PATH)
self.defcorelist = os.path.join(self.FUNCTEST_TEST,
@@ -45,7 +45,7 @@ class RefstackClient(testcase.TestCase):
cmd = ("cd {0};"
". .venv/bin/activate;"
- "cd -;".format(CONST.dir_refstack_client))
+ "cd -;".format(CONST.__getattribute__('dir_refstack_client')))
ft_utils.execute_command(cmd)
def run_defcore(self, conf, testlist):
@@ -53,7 +53,7 @@ class RefstackClient(testcase.TestCase):
cmd = ("cd {0};"
"./refstack-client test -c {1} -v --test-list {2};"
- "cd -;".format(CONST.dir_refstack_client,
+ "cd -;".format(CONST.__getattribute__('dir_refstack_client'),
conf,
testlist))
ft_utils.execute_command(cmd)
@@ -63,16 +63,16 @@ class RefstackClient(testcase.TestCase):
cmd = ("cd {0};"
"./refstack-client test -c {1} -v --test-list {2};"
- "cd -;".format(CONST.dir_refstack_client,
+ "cd -;".format(CONST.__getattribute__('dir_refstack_client'),
self.confpath,
self.defcorelist))
logger.info("Starting Refstack_defcore test case: '%s'." % cmd)
header = ("Refstack environment:\n"
" SUT: %s\n Scenario: %s\n Node: %s\n Date: %s\n" %
- (CONST.INSTALLER_TYPE,
- CONST.DEPLOY_SCENARIO,
- CONST.NODE_NAME,
+ (CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ CONST.__getattribute__('NODE_NAME'),
time.strftime("%a %b %d %H:%M:%S %Z %Y")))
f_stdout = open(
@@ -202,9 +202,9 @@ class RefstackClient(testcase.TestCase):
class RefstackClientParser(object):
def __init__(self):
- self.FUNCTEST_TEST = CONST.dir_functest_test
- self.CONF_PATH = CONST.refstack_tempest_conf_path
- self.DEFCORE_LIST = CONST.refstack_defcore_list
+ self.FUNCTEST_TEST = CONST.__getattribute__('dir_functest_test')
+ self.CONF_PATH = CONST.__getattribute__('refstack_tempest_conf_path')
+ self.DEFCORE_LIST = CONST.__getattribute__('refstack_defcore_list')
self.confpath = os.path.join(self.FUNCTEST_TEST,
self.CONF_PATH)
self.defcorelist = os.path.join(self.FUNCTEST_TEST,
diff --git a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
index 5c04253c3..fbaad589e 100755
--- a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
+++ b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
@@ -24,12 +24,14 @@ class TempestConf(object):
self.DEPLOYMENT_ID = conf_utils.get_verifier_deployment_id()
self.DEPLOYMENT_DIR = conf_utils.get_verifier_deployment_dir(
self.VERIFIER_ID, self.DEPLOYMENT_ID)
- self.confpath = os.path.join(CONST.dir_functest_test,
- CONST.refstack_tempest_conf_path)
+ self.confpath = os.path.join(
+ CONST.__getattribute__('dir_functest_test'),
+ CONST.__getattribute__('refstack_tempest_conf_path'))
def generate_tempestconf(self):
try:
- openstack_utils.source_credentials(CONST.openstack_creds)
+ openstack_utils.source_credentials(
+ CONST.__getattribute__('openstack_creds'))
img_flavor_dict = conf_utils.create_tempest_resources(
use_custom_images=True, use_custom_flavors=True)
conf_utils.configure_tempest_defcore(
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
index 94b97551a..2b98a202f 100644
--- a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
+++ b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
@@ -7,7 +7,7 @@
import logging
-from functest.core.pytest_suite_runner import PyTestSuiteRunner
+from functest.core import unit
from functest.opnfv_tests.openstack.snaps import snaps_utils
from functest.utils import functest_utils
from functest.utils.constants import CONST
@@ -16,7 +16,7 @@ from snaps.openstack import create_flavor
from snaps.openstack.tests import openstack_tests
-class SnapsTestRunner(PyTestSuiteRunner):
+class SnapsTestRunner(unit.Suite):
"""
This test executes the SNAPS Python Tests
"""
diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py
index cd6a2a8c1..556a41d4c 100644
--- a/functest/opnfv_tests/openstack/tempest/conf_utils.py
+++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py
@@ -21,11 +21,12 @@ import functest.utils.openstack_utils as os_utils
IMAGE_ID_ALT = None
FLAVOR_ID_ALT = None
-REPO_PATH = CONST.dir_repo_functest
-GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_images,
- CONST.openstack_image_file_name)
-TEMPEST_TEST_LIST_DIR = CONST.dir_tempest_cases
-TEMPEST_RESULTS_DIR = os.path.join(CONST.dir_results,
+REPO_PATH = CONST.__getattribute__('dir_repo_functest')
+GLANCE_IMAGE_PATH = os.path.join(
+ CONST.__getattribute__('dir_functest_images'),
+ CONST.__getattribute__('openstack_image_file_name'))
+TEMPEST_TEST_LIST_DIR = CONST.__getattribute__('dir_tempest_cases')
+TEMPEST_RESULTS_DIR = os.path.join(CONST.__getattribute__('dir_results'),
'tempest')
TEMPEST_CUSTOM = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
'test_list.txt')
@@ -35,11 +36,11 @@ TEMPEST_DEFCORE = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
'defcore_req.txt')
TEMPEST_RAW_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_raw_list.txt')
TEMPEST_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_list.txt')
-REFSTACK_RESULTS_DIR = os.path.join(CONST.dir_results,
+REFSTACK_RESULTS_DIR = os.path.join(CONST.__getattribute__('dir_results'),
'refstack')
-CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE
-CI_INSTALLER_IP = CONST.INSTALLER_IP
+CI_INSTALLER_TYPE = CONST.__getattribute__('INSTALLER_TYPE')
+CI_INSTALLER_IP = CONST.__getattribute__('INSTALLER_IP')
""" logging configuration """
logger = logging.getLogger(__name__)
@@ -52,26 +53,27 @@ def create_tempest_resources(use_custom_images=False,
logger.debug("Creating tenant and user for Tempest suite")
tenant_id = os_utils.create_tenant(
keystone_client,
- CONST.tempest_identity_tenant_name,
- CONST.tempest_identity_tenant_description)
+ CONST.__getattribute__('tempest_identity_tenant_name'),
+ CONST.__getattribute__('tempest_identity_tenant_description'))
if not tenant_id:
logger.error("Failed to create %s tenant"
- % CONST.tempest_identity_tenant_name)
+ % CONST.__getattribute__('tempest_identity_tenant_name'))
- user_id = os_utils.create_user(keystone_client,
- CONST.tempest_identity_user_name,
- CONST.tempest_identity_user_password,
- None, tenant_id)
+ user_id = os_utils.create_user(
+ keystone_client,
+ CONST.__getattribute__('tempest_identity_user_name'),
+ CONST.__getattribute__('tempest_identity_user_password'),
+ None, tenant_id)
if not user_id:
logger.error("Failed to create %s user" %
- CONST.tempest_identity_user_name)
+ CONST.__getattribute__('tempest_identity_user_name'))
logger.debug("Creating private network for Tempest suite")
network_dic = os_utils.create_shared_network_full(
- CONST.tempest_private_net_name,
- CONST.tempest_private_subnet_name,
- CONST.tempest_router_name,
- CONST.tempest_private_subnet_cidr)
+ CONST.__getattribute__('tempest_private_net_name'),
+ CONST.__getattribute__('tempest_private_subnet_name'),
+ CONST.__getattribute__('tempest_router_name'),
+ CONST.__getattribute__('tempest_private_subnet_cidr'))
if network_dic is None:
raise Exception('Failed to create private network')
@@ -80,41 +82,45 @@ def create_tempest_resources(use_custom_images=False,
flavor_id = ""
flavor_id_alt = ""
- if CONST.tempest_use_custom_images or use_custom_images:
+ if (CONST.__getattribute__('tempest_use_custom_images') or
+ use_custom_images):
# adding alternative image should be trivial should we need it
logger.debug("Creating image for Tempest suite")
_, image_id = os_utils.get_or_create_image(
- CONST.openstack_image_name, GLANCE_IMAGE_PATH,
- CONST.openstack_image_disk_format)
+ CONST.__getattribute__('openstack_image_name'),
+ GLANCE_IMAGE_PATH,
+ CONST.__getattribute__('openstack_image_disk_format'))
if image_id is None:
raise Exception('Failed to create image')
if use_custom_images:
logger.debug("Creating 2nd image for Tempest suite")
_, image_id_alt = os_utils.get_or_create_image(
- CONST.openstack_image_name_alt, GLANCE_IMAGE_PATH,
- CONST.openstack_image_disk_format)
+ CONST.__getattribute__('openstack_image_name_alt'),
+ GLANCE_IMAGE_PATH,
+ CONST.__getattribute__('openstack_image_disk_format'))
if image_id_alt is None:
raise Exception('Failed to create image')
- if CONST.tempest_use_custom_flavors or use_custom_flavors:
+ if (CONST.__getattribute__('tempest_use_custom_flavors') or
+ use_custom_flavors):
# adding alternative flavor should be trivial should we need it
logger.debug("Creating flavor for Tempest suite")
_, flavor_id = os_utils.get_or_create_flavor(
- CONST.openstack_flavor_name,
- CONST.openstack_flavor_ram,
- CONST.openstack_flavor_disk,
- CONST.openstack_flavor_vcpus)
+ CONST.__getattribute__('openstack_flavor_name'),
+ CONST.__getattribute__('openstack_flavor_ram'),
+ CONST.__getattribute__('openstack_flavor_disk'),
+ CONST.__getattribute__('openstack_flavor_vcpus'))
if flavor_id is None:
raise Exception('Failed to create flavor')
if use_custom_flavors:
logger.debug("Creating 2nd flavor for tempest_defcore")
_, flavor_id_alt = os_utils.get_or_create_flavor(
- CONST.openstack_flavor_name_alt,
- CONST.openstack_flavor_ram,
- CONST.openstack_flavor_disk,
- CONST.openstack_flavor_vcpus)
+ CONST.__getattribute__('openstack_flavor_name_alt'),
+ CONST.__getattribute__('openstack_flavor_ram'),
+ CONST.__getattribute__('openstack_flavor_disk'),
+ CONST.__getattribute__('openstack_flavor_vcpus'))
if flavor_id_alt is None:
raise Exception('Failed to create flavor')
@@ -132,7 +138,7 @@ def get_verifier_id():
Returns verifer id for current Tempest
"""
cmd = ("rally verify list-verifiers | awk '/" +
- CONST.tempest_deployment_name +
+ CONST.__getattribute__('tempest_deployment_name') +
"/ {print $2}'")
p = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
@@ -149,7 +155,7 @@ def get_verifier_deployment_id():
Returns deployment id for active Rally deployment
"""
cmd = ("rally deployment list | awk '/" +
- CONST.rally_deployment_name +
+ CONST.__getattribute__('rally_deployment_name') +
"/ {print $2}'")
p = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
@@ -168,7 +174,7 @@ def get_verifier_repo_dir(verifier_id):
if not verifier_id:
verifier_id = get_verifier_id()
- return os.path.join(CONST.dir_rally_inst,
+ return os.path.join(CONST.__getattribute__('dir_rally_inst'),
'verification',
'verifier-{}'.format(verifier_id),
'repo')
@@ -184,7 +190,7 @@ def get_verifier_deployment_dir(verifier_id, deployment_id):
if not deployment_id:
deployment_id = get_verifier_deployment_id()
- return os.path.join(CONST.dir_rally_inst,
+ return os.path.join(CONST.__getattribute__('dir_rally_inst'),
'verification',
'verifier-{}'.format(verifier_id),
'for-deployment-{}'.format(deployment_id))
@@ -247,8 +253,9 @@ def configure_tempest_defcore(deployment_dir, img_flavor_dict):
with open(conf_file, 'wb') as config_file:
config.write(config_file)
- confpath = os.path.join(CONST.dir_functest_test,
- CONST.refstack_tempest_conf_path)
+ confpath = os.path.join(
+ CONST.__getattribute__('dir_functest_test'),
+ CONST.__getattribute__('refstack_tempest_conf_path'))
shutil.copyfile(conf_file, confpath)
@@ -263,32 +270,37 @@ def configure_tempest_update_params(tempest_conf_file,
config.set(
'compute',
'fixed_network_name',
- CONST.tempest_private_net_name)
+ CONST.__getattribute__('tempest_private_net_name'))
config.set('compute', 'volume_device_name',
- CONST.tempest_volume_device_name)
- if CONST.tempest_use_custom_images:
+ CONST.__getattribute__('tempest_volume_device_name'))
+ if CONST.__getattribute__('tempest_use_custom_images'):
if IMAGE_ID is not None:
config.set('compute', 'image_ref', IMAGE_ID)
if IMAGE_ID_ALT is not None:
config.set('compute', 'image_ref_alt', IMAGE_ID_ALT)
- if CONST.tempest_use_custom_flavors:
+ if CONST.__getattribute__('tempest_use_custom_flavors'):
if FLAVOR_ID is not None:
config.set('compute', 'flavor_ref', FLAVOR_ID)
if FLAVOR_ID_ALT is not None:
config.set('compute', 'flavor_ref_alt', FLAVOR_ID_ALT)
- config.set('identity', 'tenant_name', CONST.tempest_identity_tenant_name)
- config.set('identity', 'username', CONST.tempest_identity_user_name)
- config.set('identity', 'password', CONST.tempest_identity_user_password)
+ config.set('identity', 'tenant_name',
+ CONST.__getattribute__('tempest_identity_tenant_name'))
+ config.set('identity', 'username',
+ CONST.__getattribute__('tempest_identity_user_name'))
+ config.set('identity', 'password',
+ CONST.__getattribute__('tempest_identity_user_password'))
config.set('identity', 'region', 'RegionOne')
config.set(
- 'validation', 'ssh_timeout', CONST.tempest_validation_ssh_timeout)
+ 'validation', 'ssh_timeout',
+ CONST.__getattribute__('tempest_validation_ssh_timeout'))
config.set('object-storage', 'operator_role',
- CONST.tempest_object_storage_operator_role)
+ CONST.__getattribute__('tempest_object_storage_operator_role'))
- if CONST.OS_ENDPOINT_TYPE is not None:
+ if CONST.__getattribute__('OS_ENDPOINT_TYPE') is not None:
sections = config.sections()
if os_utils.is_keystone_v3():
- config.set('identity', 'v3_endpoint_type', CONST.OS_ENDPOINT_TYPE)
+ config.set('identity', 'v3_endpoint_type',
+ CONST.__getattribute__('OS_ENDPOINT_TYPE'))
if 'identity-feature-enabled' not in sections:
config.add_section('identity-feature-enabled')
config.set('identity-feature-enabled', 'api_v2', False)
@@ -304,7 +316,7 @@ def configure_tempest_update_params(tempest_conf_file,
if service not in sections:
config.add_section(service)
config.set(service, 'endpoint_type',
- CONST.OS_ENDPOINT_TYPE)
+ CONST.__getattribute__('OS_ENDPOINT_TYPE'))
with open(tempest_conf_file, 'wb') as config_file:
config.write(config_file)
@@ -365,22 +377,22 @@ def configure_tempest_multisite_params(tempest_conf_file):
"StrictHostKeyChecking=no")
# Get the controller IP from the fuel node
- cmd = 'sshpass -p %s ssh 2>/dev/null %s %s@%s \
- \'fuel node --env 1| grep controller | grep "True\| 1" \
- | awk -F\| "{print \$5}"\'' % (installer_password,
+ cmd = ('sshpass -p %s ssh 2>/dev/null %s %s@%s '
+ '\'fuel node --env 1| grep controller | grep "True\| 1" '
+ '| awk -F\| "{print \$5}"\'' % (installer_password,
ssh_options,
installer_username,
- installer_ip)
+ installer_ip))
multisite_controller_ip = "".join(os.popen(cmd).read().split())
# Login to controller and get bind host details
- cmd = 'sshpass -p %s ssh 2>/dev/null %s %s@%s "ssh %s \\" \
- grep -e "^bind_" %s \\""' % (installer_password,
- ssh_options,
- installer_username,
- installer_ip,
- multisite_controller_ip,
- kingbird_conf_path)
+ cmd = ('sshpass -p %s ssh 2>/dev/null %s %s@%s "ssh %s \\" '
+ 'grep -e "^bind_" %s \\""' % (installer_password,
+ ssh_options,
+ installer_username,
+ installer_ip,
+ multisite_controller_ip,
+ kingbird_conf_path))
bind_details = os.popen(cmd).read()
bind_details = "".join(bind_details.split())
# Extract port number from the bind details
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index a41d07c7e..f5f194e67 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -81,8 +81,8 @@ class TempestCommon(testcase.TestCase):
result_file = open(conf_utils.TEMPEST_LIST, 'w')
black_tests = []
try:
- installer_type = CONST.INSTALLER_TYPE
- deploy_scenario = CONST.DEPLOY_SCENARIO
+ installer_type = CONST.__getattribute__('INSTALLER_TYPE')
+ deploy_scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
if (bool(installer_type) * bool(deploy_scenario)):
# if INSTALLER_TYPE and DEPLOY_SCENARIO are set we read the
# file
@@ -119,9 +119,9 @@ class TempestCommon(testcase.TestCase):
header = ("Tempest environment:\n"
" SUT: %s\n Scenario: %s\n Node: %s\n Date: %s\n" %
- (CONST.INSTALLER_TYPE,
- CONST.DEPLOY_SCENARIO,
- CONST.NODE_NAME,
+ (CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ CONST.__getattribute__('NODE_NAME'),
time.strftime("%a %b %d %H:%M:%S %Z %Y")))
f_stdout = open(
@@ -148,7 +148,7 @@ class TempestCommon(testcase.TestCase):
first_pos = line.index("UUID=") + len("UUID=")
last_pos = line.index(") for deployment")
self.VERIFICATION_ID = line[first_pos:last_pos]
- logger.debug('Verication UUID: %s' % self.VERIFICATION_ID)
+ logger.debug('Verification UUID: %s', self.VERIFICATION_ID)
f_stdout.write(line)
p.wait()
@@ -273,7 +273,8 @@ class TempestMultisite(TempestCommon):
TempestCommon.__init__(self, **kwargs)
self.MODE = "feature_multisite"
self.OPTION = "--concurrency 1"
- conf_utils.install_verifier_ext(CONST.dir_repo_kingbird)
+ conf_utils.install_verifier_ext(
+ CONST.__getattribute__('dir_repo_kingbird'))
class TempestCustom(TempestCommon):
diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py
index 6f586b7a0..b2b0b77c6 100755
--- a/functest/opnfv_tests/sdn/odl/odl.py
+++ b/functest/opnfv_tests/sdn/odl/odl.py
@@ -30,6 +30,7 @@ import robot.api
from robot.errors import RobotError
import robot.run
from robot.utils.robottime import timestamp_to_secs
+from six import StringIO
from six.moves import urllib
from functest.core import testcase
@@ -107,7 +108,7 @@ class ODLTests(testcase.TestCase):
result.suite.statistics.critical.passed /
result.suite.statistics.critical.total)
except ZeroDivisionError:
- self.__logger.error("No test has been ran")
+ self.__logger.error("No test has been run")
self.start_time = timestamp_to_secs(result.suite.starttime)
self.stop_time = timestamp_to_secs(result.suite.endtime)
self.details = {}
@@ -172,16 +173,11 @@ class ODLTests(testcase.TestCase):
self.__logger.exception(
"Cannot create %s", self.res_dir)
return self.EX_RUN_ERROR
- stdout_file = os.path.join(self.res_dir, 'stdout.txt')
output_dir = os.path.join(self.res_dir, 'output.xml')
- with open(stdout_file, 'w+') as stdout:
- robot.run(*suites, variable=variables,
- output=output_dir,
- log='NONE',
- report='NONE',
- stdout=stdout)
- stdout.seek(0, 0)
- self.__logger.info("\n" + stdout.read())
+ stream = StringIO()
+ robot.run(*suites, variable=variables, output=output_dir,
+ log='NONE', report='NONE', stdout=stream)
+ self.__logger.info("\n" + stream.getvalue())
self.__logger.info("ODL results were successfully generated")
try:
self.parse_results()
@@ -190,10 +186,6 @@ class ODLTests(testcase.TestCase):
self.__logger.error("Run tests before publishing: %s",
ex.message)
return self.EX_RUN_ERROR
- try:
- os.remove(stdout_file)
- except OSError:
- self.__logger.warning("Cannot remove %s", stdout_file)
return self.EX_OK
else:
return self.EX_RUN_ERROR
diff --git a/functest/opnfv_tests/sdn/onos/onos.py b/functest/opnfv_tests/sdn/onos/onos.py
index 5dfff036b..adcb41666 100644
--- a/functest/opnfv_tests/sdn/onos/onos.py
+++ b/functest/opnfv_tests/sdn/onos/onos.py
@@ -209,10 +209,10 @@ class OnosSfc(OnosBase):
self.onos_sfc_image_name, image_id)
def set_sfc_conf(self):
- self.update_sfc_onos_file("keystone_ip", self.get_ip("keystone"))
- self.update_sfc_onos_file("neutron_ip", self.get_ip("neutron"))
- self.update_sfc_onos_file("nova_ip", self.get_ip("nova"))
- self.update_sfc_onos_file("glance_ip", self.get_ip("glance"))
+ self.update_sfc_onos_file("keystone_ip", self.get_ip("identity"))
+ self.update_sfc_onos_file("neutron_ip", self.get_ip("network"))
+ self.update_sfc_onos_file("nova_ip", self.get_ip("compute"))
+ self.update_sfc_onos_file("glance_ip", self.get_ip("image"))
self.update_sfc_onos_file("console",
CONST.__getattribute__('OS_PASSWORD'))
neutron_client = openstack_utils.get_neutron_client()
diff --git a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py b/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
index 1101f2394..4e93c1337 100644
--- a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
+++ b/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
@@ -100,8 +100,10 @@ class SfcOnos(object):
self.ip_pool = 0
self.vm_public_ip = []
self.vm_public_id = []
- self.cirros_username = CONST.openstack_image_username
- self.cirros_password = CONST.openstack_image_password
+ self.cirros_username = CONST.__getattribute__(
+ 'openstack_image_username')
+ self.cirros_password = CONST.__getattribute__(
+ 'openstack_image_password')
self.net_id1 = 0
self.vm = []
self.address = 0
@@ -115,7 +117,7 @@ class SfcOnos(object):
data = ('{"auth": {"tenantName": "admin", "passwordCredentials":'
'{ "username": "admin", "password": "console"}}}')
headers = {"Accept": "application/json"}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == OK):
json1_data = json.loads(response.content)
self.logger.debug(response.status_code)
@@ -135,12 +137,12 @@ class SfcOnos(object):
if self.admin_state_up != '':
Dicdata['admin_state_up'] = self.admin_state_up
Dicdata = {'network': Dicdata}
- data = json.dumps(Dicdata, indent=4)
+ data = json.dumps(Dicdata, indent=4)
url = 'http://%s:9696/%s/networks' % (self.neutron_hostname,
self.osver)
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -170,7 +172,7 @@ class SfcOnos(object):
self.osver)
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
self.logger.debug(response.status_code)
@@ -203,7 +205,7 @@ class SfcOnos(object):
self.osver)
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
self.logger.debug(response.status_code)
@@ -222,8 +224,9 @@ class SfcOnos(object):
"""Creation of Instance, using firewall image."""
url = ("http://%s:9292/v2/images?"
"name=TestSfcVm" % (self.glance_hostname))
- headers = {"Accept": "application/json", "Content-Type": "application/\
- octet-stream", "X-Auth-Token": self.token_id}
+ headers = {"Accept": "application/json",
+ "Content-Type": "application/octet-stream",
+ "X-Auth-Token": self.token_id}
response = requests.get(url, headers=headers)
if (response.status_code == OK):
self.logger.debug(response.status_code)
@@ -273,7 +276,7 @@ class SfcOnos(object):
self.tenant_id)
headers = {"Accept": "application/json", "Content-Type":
"application/json", "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == ACCEPTED):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -295,8 +298,8 @@ class SfcOnos(object):
for y in range(0, 3):
url = ("http://%s:8774/v2.1/servers/"
"detail?name=vm" + str(y)) % (self.neutron_hostname)
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
+ headers = {"Accept": "application/json",
+ "X-Auth-Token": self.token_id}
response = requests.get(url, headers=headers)
if (response.status_code == OK):
self.logger.debug(response.status_code)
@@ -332,7 +335,7 @@ class SfcOnos(object):
self.osver)
headers = {"Accept": "application/json", "X-Auth-Token":
self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
info = ("Creation of Port Pair PP" + str(p) +
" is successful")
@@ -380,7 +383,7 @@ class SfcOnos(object):
self.osver))
headers = {"Accept": "application/json", "X-Auth-Token":
self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
info = ("Creation of Port Group PG" + str(p) +
"is successful")
@@ -431,7 +434,7 @@ class SfcOnos(object):
self.osver))
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
json1_data = json.loads(response.content)
self.flow_class_if = json1_data['flow_classifier']['id']
@@ -462,7 +465,7 @@ class SfcOnos(object):
headers = {"Accept": "application/json",
"Content-Type": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
self.logger.debug("Creation of PORT CHAIN is successful")
json1_data = json.loads(response.content)
@@ -476,7 +479,7 @@ class SfcOnos(object):
time.sleep(5)
response = requests.get('http://' + self.onos_hostname +
':8181/onos/v1/flows',
- auth=("karaf", "karaf"))
+ auth=("karaf", "karaf"))
if (response.status_code == OK):
self.logger.debug("Flow is successfully Queries")
json1_data = json.loads(response.content)
@@ -505,7 +508,7 @@ class SfcOnos(object):
self.osver)
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == CREATED):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -548,7 +551,7 @@ class SfcOnos(object):
self.router_id))
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
+ response = requests.put(url, headers=headers, data=data)
if (response.status_code == OK):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -570,7 +573,7 @@ class SfcOnos(object):
self.router_id)
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
+ response = requests.put(url, headers=headers, data=data)
if (response.status_code == OK):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -590,7 +593,7 @@ class SfcOnos(object):
"os-floating-ips" % (self.nova_hostname))
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if (response.status_code == OK):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -614,7 +617,7 @@ class SfcOnos(object):
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
+ response = requests.post(url, headers=headers, data=data)
if(response.status_code == ACCEPTED):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -631,12 +634,12 @@ class SfcOnos(object):
s = pxssh.pxssh()
hostname = self.vm_public_ip[0]
- s.login(hostname, self.cirros_username, self.cirros_password)
+ s.login(hostname, self.cirros_username, self.cirros_password)
s.sendline("ping -c 5 " + str(self.port_ip[2]))
s.prompt() # match the prompt
- ping_re = re.search("transmitted.*received", s.before).group()
- x = re.split('\s+', ping_re)
+ ping_re = re.search("transmitted.*received", s.before).group()
+ x = re.split('\s+', ping_re)
if (x[1] >= "1"):
self.logger.info("Ping is Successfull")
else:
@@ -645,7 +648,7 @@ class SfcOnos(object):
def vm1(queue1):
s = pxssh.pxssh()
hostname = self.vm_public_ip[1]
- s.login(hostname, self.cirros_username, self.cirros_password)
+ s.login(hostname, self.cirros_username, self.cirros_password)
s.sendline('sudo ./firewall')
s.prompt()
output_pack = s.before
@@ -676,7 +679,7 @@ class SfcOnos(object):
if result0 == 0 and result1 == 0:
time.sleep(300)
queue1 = Queue()
- p1 = Process(target=vm1, args=(queue1, ))
+ p1 = Process(target=vm1, args=(queue1, ))
p1.start()
p2 = Process(target=vm0)
p2.start()
@@ -703,7 +706,7 @@ class SfcOnos(object):
"""Check the PC SF Map Stats in the ONOS."""
response = requests.get('http://' + self.onos_hostname +
':8181/onos/vtn/portChainSfMap/' +
- self.PC_id, auth=("karaf", "karaf"))
+ self.PC_id, auth=("karaf", "karaf"))
if (response.status_code == OK):
self.logger.info("portChainSfMap is successfully Queries")
return(response.status_code)
@@ -761,7 +764,7 @@ class SfcOnos(object):
def deletePortPair(self):
"""Deletion of Portpair."""
- for p in range(1, 2):
+ for p in range(1, 2):
url = ("http://%s:9696/%s/sfc/"
"port_pairs/%s" % (self.neutron_hostname,
self.osver,
@@ -819,7 +822,7 @@ class SfcOnos(object):
self.router_id))
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
+ response = requests.put(url, headers=headers, data=data)
if (response.status_code == OK):
self.logger.debug(response.status_code)
self.logger.debug(response.content)
@@ -833,14 +836,14 @@ class SfcOnos(object):
self.router_id))
headers = {"Accept": "application/json",
"X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
+ response = requests.put(url, headers=headers, data=data)
if (response.status_code == OK):
url = ("http://%s:9696/%s/"
"routers/%s" % (self.neutron_hostname,
self.osver,
self.router_id))
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
+ headers = {"Accept": "application/json",
+ "X-Auth-Token": self.token_id}
response = requests.delete(url, headers=headers)
if (response.status_code == NO_CONTENT):
self.logger.debug(response.status_code)
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py b/functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py
index 25421d400..f9eee7af6 100644
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py
+++ b/functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py
@@ -26,7 +26,8 @@ class Foundation(object):
def __init__(self):
# currentpath = os.getcwd()
- currentpath = '%s/sdn/onos/teston/ci' % CONST.dir_functest_data
+ currentpath = ('{0}/sdn/onos/teston/ci'
+ .format(CONST.__getattribute__('dir_functest_data')))
self.cipath = currentpath
self.logdir = os.path.join(currentpath, 'log')
self.workhome = currentpath[0: currentpath.rfind('opnfv_tests') - 1]
@@ -55,22 +56,25 @@ class Foundation(object):
Get Default Parameters value
"""
self.Result_DB = ft_utils.get_db_url()
- self.masterusername = CONST.ONOS_onosbench_username
- self.masterpassword = CONST.ONOS_onosbench_password
- self.agentusername = CONST.ONOS_onoscli_username
- self.agentpassword = CONST.ONOS_onoscli_password
- self.runtimeout = CONST.ONOS_runtimeout
- self.OCT = CONST.ONOS_environment_OCT
- self.OC1 = CONST.ONOS_environment_OC1
- self.OC2 = CONST.ONOS_environment_OC2
- self.OC3 = CONST.ONOS_environment_OC3
- self.OCN = CONST.ONOS_environment_OCN
- self.OCN2 = CONST.ONOS_environment_OCN2
- self.installer_master = CONST.ONOS_environment_installer_master
+ self.masterusername = CONST.__getattribute__('ONOS_onosbench_username')
+ self.masterpassword = CONST.__getattribute__('ONOS_onosbench_password')
+ self.agentusername = CONST.__getattribute__('ONOS_onoscli_username')
+ self.agentpassword = CONST.__getattribute__('ONOS_onoscli_password')
+ self.runtimeout = CONST.__getattribute__('ONOS_runtimeout')
+ self.OCT = CONST.__getattribute__('ONOS_environment_OCT')
+ self.OC1 = CONST.__getattribute__('ONOS_environment_OC1')
+ self.OC2 = CONST.__getattribute__('ONOS_environment_OC2')
+ self.OC3 = CONST.__getattribute__('ONOS_environment_OC3')
+ self.OCN = CONST.__getattribute__('ONOS_environment_OCN')
+ self.OCN2 = CONST.__getattribute__('ONOS_environment_OCN2')
+ self.installer_master = CONST.__getattribute__(
+ 'ONOS_environment_installer_master')
self.installer_master_username = (
- CONST.ONOS_environment_installer_master_username)
+ CONST.__getattribute__(
+ 'ONOS_environment_installer_master_username'))
self.installer_master_password = (
- CONST.ONOS_environment_installer_master_password)
+ CONST.__getattribute__(
+ 'ONOS_environment_installer_master_password'))
self.hosts = [self.OC1, self.OCN, self.OCN2]
self.localhost = self.OCT
diff --git a/functest/tests/unit/ci/test_prepare_env.py b/functest/tests/unit/ci/test_prepare_env.py
index fbb596512..513e72308 100644
--- a/functest/tests/unit/ci/test_prepare_env.py
+++ b/functest/tests/unit/ci/test_prepare_env.py
@@ -18,8 +18,6 @@ from opnfv.utils import constants as opnfv_constants
class PrepareEnvTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.prepare_envparser = prepare_env.PrepareEnvParser()
@@ -464,4 +462,5 @@ class PrepareEnvTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/ci/test_run_tests.py b/functest/tests/unit/ci/test_run_tests.py
index d0052392f..88e5d2b86 100644
--- a/functest/tests/unit/ci/test_run_tests.py
+++ b/functest/tests/unit/ci/test_run_tests.py
@@ -5,21 +5,32 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
-
-import unittest
import logging
+import unittest
import mock
from functest.ci import run_tests
from functest.utils.constants import CONST
+from functest.core.testcase import TestCase
-class RunTestsTesting(unittest.TestCase):
+class FakeModule(TestCase):
+
+ def run(self):
+ return TestCase.EX_OK
+
+ def push_to_db(self):
+ return TestCase.EX_OK
+
+ def is_successful(self):
+ return TestCase.EX_OK
- logging.disable(logging.CRITICAL)
+
+class RunTestsTesting(unittest.TestCase):
def setUp(self):
+ self.runner = run_tests.Runner()
self.sep = 'test_sep'
self.creds = {'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
'OS_USERNAME': 'test_os_username',
@@ -38,11 +49,10 @@ class RunTestsTesting(unittest.TestCase):
self.tiers.configure_mock(**attrs)
self.run_tests_parser = run_tests.RunTestsParser()
- self.global_variables = run_tests.GlobalVariables()
@mock.patch('functest.ci.run_tests.logger.info')
def test_print_separator(self, mock_logger_info):
- run_tests.print_separator(self.sep)
+ self.runner.print_separator(self.sep)
mock_logger_info.assert_called_once_with(self.sep * 44)
@mock.patch('functest.ci.run_tests.logger.error')
@@ -50,24 +60,24 @@ class RunTestsTesting(unittest.TestCase):
with mock.patch('functest.ci.run_tests.os.path.isfile',
return_value=False), \
self.assertRaises(Exception):
- run_tests.source_rc_file()
+ self.runner.source_rc_file()
@mock.patch('functest.ci.run_tests.logger.debug')
- def test_source_rc_file_default(self, mock_logger_debug):
- with mock.patch('functest.ci.run_tests.os.path.isfile',
- return_value=True), \
- mock.patch('functest.ci.run_tests.os_utils.source_credentials',
- return_value=self.creds):
- run_tests.source_rc_file()
+ @mock.patch('functest.ci.run_tests.os.path.isfile',
+ return_value=True)
+ def test_source_rc_file_default(self, *args):
+ with mock.patch('functest.ci.run_tests.os_utils.source_credentials',
+ return_value=self.creds):
+ self.runner.source_rc_file()
@mock.patch('functest.ci.run_tests.os_snapshot.main')
def test_generate_os_snapshot(self, mock_os_snap):
- run_tests.generate_os_snapshot()
+ self.runner.generate_os_snapshot()
self.assertTrue(mock_os_snap.called)
@mock.patch('functest.ci.run_tests.os_clean.main')
def test_cleanup(self, mock_os_clean):
- run_tests.cleanup()
+ self.runner.cleanup()
self.assertTrue(mock_os_clean.called)
def test_get_run_dict_if_defined_default(self):
@@ -75,7 +85,7 @@ class RunTestsTesting(unittest.TestCase):
with mock.patch('functest.ci.run_tests.'
'ft_utils.get_dict_by_test',
return_value={'run': mock_obj}):
- self.assertEqual(run_tests.get_run_dict('test_name'),
+ self.assertEqual(self.runner.get_run_dict('test_name'),
mock_obj)
@mock.patch('functest.ci.run_tests.logger.error')
@@ -85,7 +95,7 @@ class RunTestsTesting(unittest.TestCase):
'ft_utils.get_dict_by_test',
return_value=None):
testname = 'test_name'
- self.assertEqual(run_tests.get_run_dict(testname),
+ self.assertEqual(self.runner.get_run_dict(testname),
None)
mock_logger_error.assert_called_once_with("Cannot get {}'s config "
"options"
@@ -95,7 +105,7 @@ class RunTestsTesting(unittest.TestCase):
'ft_utils.get_dict_by_test',
return_value={}):
testname = 'test_name'
- self.assertEqual(run_tests.get_run_dict(testname),
+ self.assertEqual(self.runner.get_run_dict(testname),
None)
@mock.patch('functest.ci.run_tests.logger.exception')
@@ -105,7 +115,7 @@ class RunTestsTesting(unittest.TestCase):
'ft_utils.get_dict_by_test',
side_effect=Exception):
testname = 'test_name'
- self.assertEqual(run_tests.get_run_dict(testname),
+ self.assertEqual(self.runner.get_run_dict(testname),
None)
mock_logger_except.assert_called_once_with("Cannot get {}'s config"
" options"
@@ -116,63 +126,67 @@ class RunTestsTesting(unittest.TestCase):
args = {'get_name.return_value': 'test_name',
'needs_clean.return_value': False}
mock_test.configure_mock(**args)
- with mock.patch('functest.ci.run_tests.print_separator'),\
- mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.get_run_dict',
+ with mock.patch('functest.ci.run_tests.Runner.print_separator'),\
+ mock.patch('functest.ci.run_tests.Runner.source_rc_file'), \
+ mock.patch('functest.ci.run_tests.Runner.get_run_dict',
return_value=None), \
self.assertRaises(Exception) as context:
- run_tests.run_test(mock_test, 'tier_name')
+ self.runner(mock_test, 'tier_name')
msg = "Cannot import the class for the test case."
self.assertTrue(msg in context)
- def test_run_tests_default(self):
+ @mock.patch('functest.ci.run_tests.Runner.print_separator')
+ @mock.patch('functest.ci.run_tests.Runner.source_rc_file')
+ @mock.patch('functest.ci.run_tests.Runner.generate_os_snapshot')
+ @mock.patch('functest.ci.run_tests.Runner.cleanup')
+ @mock.patch('importlib.import_module', name="module",
+ return_value=mock.Mock(test_class=mock.Mock(
+ side_effect=FakeModule)))
+ @mock.patch('functest.utils.functest_utils.get_dict_by_test')
+ def test_run_tests_default(self, *args):
mock_test = mock.Mock()
- args = {'get_name.return_value': 'test_name',
- 'needs_clean.return_value': True}
- mock_test.configure_mock(**args)
+ kwargs = {'get_name.return_value': 'test_name',
+ 'needs_clean.return_value': True}
+ mock_test.configure_mock(**kwargs)
test_run_dict = {'module': 'test_module',
- 'class': mock.Mock,
- 'args': 'test_args'}
- with mock.patch('functest.ci.run_tests.print_separator'),\
- mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.generate_os_snapshot'), \
- mock.patch('functest.ci.run_tests.cleanup'), \
- mock.patch('functest.ci.run_tests.get_run_dict',
- return_value=test_run_dict), \
- self.assertRaises(run_tests.BlockingTestFailed) as context:
- run_tests.GlobalVariables.CLEAN_FLAG = True
- run_tests.run_test(mock_test, 'tier_name')
- msg = 'The test case test_name failed and is blocking'
- self.assertTrue(msg in context)
+ 'class': 'test_class'}
+ with mock.patch('functest.ci.run_tests.Runner.get_run_dict',
+ return_value=test_run_dict):
+ self.runner.clean_flag = True
+ self.runner.run_test(mock_test, 'tier_name')
+ self.assertEqual(self.runner.overall_result,
+ run_tests.Result.EX_OK)
@mock.patch('functest.ci.run_tests.logger.info')
def test_run_tier_default(self, mock_logger_info):
- with mock.patch('functest.ci.run_tests.print_separator'), \
- mock.patch('functest.ci.run_tests.run_test') as mock_method:
- run_tests.run_tier(self.tier)
+ with mock.patch('functest.ci.run_tests.Runner.print_separator'), \
+ mock.patch(
+ 'functest.ci.run_tests.Runner.run_test') as mock_method:
+ self.runner.run_tier(self.tier)
mock_method.assert_any_call('test1', 'test_tier')
mock_method.assert_any_call('test2', 'test_tier')
self.assertTrue(mock_logger_info.called)
@mock.patch('functest.ci.run_tests.logger.info')
def test_run_tier_missing_test(self, mock_logger_info):
- with mock.patch('functest.ci.run_tests.print_separator'):
+ with mock.patch('functest.ci.run_tests.Runner.print_separator'):
self.tier.get_tests.return_value = None
- self.assertEqual(run_tests.run_tier(self.tier), 0)
+ self.assertEqual(self.runner.run_tier(self.tier), 0)
self.assertTrue(mock_logger_info.called)
@mock.patch('functest.ci.run_tests.logger.info')
def test_run_all_default(self, mock_logger_info):
- with mock.patch('functest.ci.run_tests.run_tier') as mock_method:
+ with mock.patch(
+ 'functest.ci.run_tests.Runner.run_tier') as mock_method:
CONST.__setattr__('CI_LOOP', 'test_ci_loop')
- run_tests.run_all(self.tiers)
+ self.runner.run_all(self.tiers)
mock_method.assert_any_call(self.tier)
self.assertTrue(mock_logger_info.called)
@mock.patch('functest.ci.run_tests.logger.info')
def test_run_all_missing_tier(self, mock_logger_info):
CONST.__setattr__('CI_LOOP', 'loop_re_not_available')
- run_tests.run_all(self.tiers)
+ self.runner.run_all(self.tiers)
self.assertTrue(mock_logger_info.called)
def test_main_failed(self):
@@ -181,72 +195,82 @@ class RunTestsTesting(unittest.TestCase):
args = {'get_tier.return_value': False,
'get_test.return_value': False}
mock_obj.configure_mock(**args)
-
with mock.patch('functest.ci.run_tests.tb.TierBuilder'), \
- mock.patch('functest.ci.run_tests.source_rc_file',
+ mock.patch('functest.ci.run_tests.Runner.source_rc_file',
side_effect=Exception):
- self.assertEqual(run_tests.main(**kwargs),
+ self.assertEqual(self.runner.main(**kwargs),
run_tests.Result.EX_ERROR)
-
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
- mock.patch('functest.ci.run_tests.source_rc_file',
+ mock.patch('functest.ci.run_tests.Runner.source_rc_file',
side_effect=Exception):
- self.assertEqual(run_tests.main(**kwargs),
+ self.assertEqual(self.runner.main(**kwargs),
run_tests.Result.EX_ERROR)
- def test_main_default(self):
- kwargs = {'test': 'test_name', 'noclean': True, 'report': True}
+ def test_main_tier(self, *args):
+ mock_tier = mock.Mock()
+ args = {'get_name.return_value': 'tier_name'}
+ mock_tier.configure_mock(**args)
+ kwargs = {'test': 'tier_name', 'noclean': True, 'report': True}
mock_obj = mock.Mock()
- args = {'get_tier.return_value': True,
- 'get_test.return_value': False}
+ args = {'get_tier.return_value': mock_tier,
+ 'get_test.return_value': None}
mock_obj.configure_mock(**args)
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
- mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.run_tier') as m:
- self.assertEqual(run_tests.main(**kwargs),
+ mock.patch('functest.ci.run_tests.Runner.source_rc_file'), \
+ mock.patch('functest.ci.run_tests.Runner.run_tier') as m:
+ self.assertEqual(self.runner.main(**kwargs),
run_tests.Result.EX_OK)
self.assertTrue(m.called)
+ def test_main_test(self, *args):
+ kwargs = {'test': 'test_name', 'noclean': True, 'report': True}
+ mock_test = mock.Mock()
+ args = {'get_name.return_value': 'test_name',
+ 'needs_clean.return_value': True}
+ mock_test.configure_mock(**args)
mock_obj = mock.Mock()
- args = {'get_tier.return_value': False,
- 'get_test.return_value': True}
+ args = {'get_tier.return_value': None,
+ 'get_test.return_value': mock_test}
mock_obj.configure_mock(**args)
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
- mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.run_test') as m:
- self.assertEqual(run_tests.main(**kwargs),
+ mock.patch('functest.ci.run_tests.Runner.source_rc_file'), \
+ mock.patch('functest.ci.run_tests.Runner.run_test') as m:
+ self.assertEqual(self.runner.main(**kwargs),
run_tests.Result.EX_OK)
self.assertTrue(m.called)
+ def test_main_all_tier(self, *args):
kwargs = {'test': 'all', 'noclean': True, 'report': True}
mock_obj = mock.Mock()
- args = {'get_tier.return_value': False,
- 'get_test.return_value': False}
+ args = {'get_tier.return_value': None,
+ 'get_test.return_value': None}
mock_obj.configure_mock(**args)
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
- mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.run_all') as m:
- self.assertEqual(run_tests.main(**kwargs),
+ mock.patch('functest.ci.run_tests.Runner.source_rc_file'), \
+ mock.patch('functest.ci.run_tests.Runner.run_all') as m:
+ self.assertEqual(self.runner.main(**kwargs),
run_tests.Result.EX_OK)
self.assertTrue(m.called)
+ def test_main_any_tier_test_ko(self, *args):
kwargs = {'test': 'any', 'noclean': True, 'report': True}
mock_obj = mock.Mock()
- args = {'get_tier.return_value': False,
- 'get_test.return_value': False}
+ args = {'get_tier.return_value': None,
+ 'get_test.return_value': None}
mock_obj.configure_mock(**args)
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
- mock.patch('functest.ci.run_tests.source_rc_file'), \
+ mock.patch('functest.ci.run_tests.Runner.source_rc_file'), \
mock.patch('functest.ci.run_tests.logger.debug') as m:
- self.assertEqual(run_tests.main(**kwargs),
+ self.assertEqual(self.runner.main(**kwargs),
run_tests.Result.EX_ERROR)
self.assertTrue(m.called)
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/ci/test_tier_builder.py b/functest/tests/unit/ci/test_tier_builder.py
index feaf33a81..989c0870f 100644
--- a/functest/tests/unit/ci/test_tier_builder.py
+++ b/functest/tests/unit/ci/test_tier_builder.py
@@ -15,8 +15,6 @@ from functest.ci import tier_builder
class TierBuilderTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.dependency = {'installer': 'test_installer',
'scenario': 'test_scenario'}
@@ -88,4 +86,5 @@ class TierBuilderTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/ci/test_tier_handler.py b/functest/tests/unit/ci/test_tier_handler.py
index 280062743..c93fffd36 100644
--- a/functest/tests/unit/ci/test_tier_handler.py
+++ b/functest/tests/unit/ci/test_tier_handler.py
@@ -15,8 +15,6 @@ from functest.ci import tier_handler
class TierHandlerTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.test = mock.Mock()
attrs = {'get_name.return_value': 'test_name'}
@@ -139,4 +137,5 @@ class TierHandlerTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/commands/test_cli_env.py b/functest/tests/unit/cli/commands/test_cli_env.py
index 4b6ea57a7..14e926eb9 100644
--- a/functest/tests/unit/cli/commands/test_cli_env.py
+++ b/functest/tests/unit/cli/commands/test_cli_env.py
@@ -18,8 +18,6 @@ from functest.tests.unit import test_utils
class CliEnvTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.cli_environ = cli_env.CliEnv()
@@ -28,7 +26,7 @@ class CliEnvTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_prepare_default(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/prepare_env.py start" %
- CONST.dir_repo_functest)
+ CONST.__getattribute__('dir_repo_functest'))
self.cli_environ.prepare()
mock_ft_utils.assert_called_with(cmd)
@@ -40,29 +38,30 @@ class CliEnvTesting(unittest.TestCase):
mock.patch('functest.cli.commands.cli_testcase.os.remove') \
as mock_os_remove:
cmd = ("python %s/functest/ci/prepare_env.py start" %
- CONST.dir_repo_functest)
+ CONST.__getattribute__('dir_repo_functest'))
self.cli_environ.prepare()
- mock_os_remove.assert_called_once_with(CONST.env_active)
+ mock_os_remove.assert_called_once_with(
+ CONST.__getattribute__('env_active'))
mock_ft_utils.assert_called_with(cmd)
def _test_show_missing_env_var(self, var, *args):
if var == 'INSTALLER_TYPE':
- CONST.INSTALLER_TYPE = None
+ CONST.__setattr__('INSTALLER_TYPE', None)
reg_string = "| INSTALLER: Unknown, \S+\s*|"
elif var == 'INSTALLER_IP':
- CONST.INSTALLER_IP = None
+ CONST.__setattr__('INSTALLER_IP', None)
reg_string = "| INSTALLER: \S+, Unknown\s*|"
elif var == 'SCENARIO':
- CONST.DEPLOY_SCENARIO = None
+ CONST.__setattr__('DEPLOY_SCENARIO', None)
reg_string = "| SCENARIO: Unknown\s*|"
elif var == 'NODE':
- CONST.NODE_NAME = None
+ CONST.__setattr__('NODE_NAME', None)
reg_string = "| POD: Unknown\s*|"
elif var == 'BUILD_TAG':
- CONST.BUILD_TAG = None
+ CONST.__setattr__('BUILD_TAG', None)
reg_string = "| BUILD TAG: None|"
elif var == 'DEBUG':
- CONST.CI_DEBUG = None
+ CONST.__setattr__('CI_DEBUG', None)
reg_string = "| DEBUG FLAG: false\s*|"
elif var == 'STATUS':
reg_string = "| STATUS: not ready\s*|"
@@ -106,7 +105,7 @@ class CliEnvTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_env.os.path.exists',
return_value=False)
def test_show_missing_git_repo_dir(self, *args):
- CONST.dir_repo_functest = None
+ CONST.__setattr__('dir_repo_functest', None)
self.assertRaises(NoSuchPathError, lambda: self.cli_environ.show())
@mock.patch('functest.cli.commands.cli_env.click.echo')
@@ -127,4 +126,5 @@ class CliEnvTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/commands/test_cli_os.py b/functest/tests/unit/cli/commands/test_cli_os.py
index f0e58c676..b551ee4d2 100644
--- a/functest/tests/unit/cli/commands/test_cli_os.py
+++ b/functest/tests/unit/cli/commands/test_cli_os.py
@@ -18,7 +18,6 @@ from functest.utils.constants import CONST
class CliOpenStackTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
def setUp(self):
self.endpoint_ip = 'test_ip'
@@ -69,11 +68,10 @@ class CliOpenStackTesting(unittest.TestCase):
def test_fetch_credentials_default(self, mock_click_echo,
mock_os_path,
mock_ftutils_execute):
- CONST.INSTALLER_TYPE = self.installer_type
- CONST.INSTALLER_IP = self.installer_ip
- cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
- self.openstack_creds,
+ CONST.__setattr__('INSTALLER_TYPE', self.installer_type)
+ CONST.__setattr__('INSTALLER_IP', self.installer_ip)
+ cmd = ("fetch_os_creds.sh -d %s -i %s -a %s"
+ % (self.openstack_creds,
self.installer_type,
self.installer_ip))
self.cli_os.openstack_creds = self.openstack_creds
@@ -92,15 +90,12 @@ class CliOpenStackTesting(unittest.TestCase):
def test_fetch_credentials_missing_installer_type(self, mock_click_echo,
mock_os_path,
mock_ftutils_execute):
- installer_type = None
- installer_ip = self.installer_ip
- CONST.INSTALLER_TYPE = installer_type
- CONST.INSTALLER_IP = installer_ip
- cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
- self.openstack_creds,
- installer_type,
- installer_ip))
+ CONST.__setattr__('INSTALLER_TYPE', None)
+ CONST.__setattr__('INSTALLER_IP', self.installer_ip)
+ cmd = ("fetch_os_creds.sh -d %s -i %s -a %s"
+ % (self.openstack_creds,
+ None,
+ self.installer_ip))
self.cli_os.openstack_creds = self.openstack_creds
self.cli_os.fetch_credentials()
mock_click_echo.assert_any_call("The environment variable "
@@ -109,8 +104,8 @@ class CliOpenStackTesting(unittest.TestCase):
mock_click_echo.assert_any_call("Fetching credentials from "
"installer node '%s' with "
"IP=%s.." %
- (installer_type,
- installer_ip))
+ (None,
+ self.installer_ip))
mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
@mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
@@ -122,11 +117,10 @@ class CliOpenStackTesting(unittest.TestCase):
mock_ftutils_execute):
installer_type = self.installer_type
installer_ip = None
- CONST.INSTALLER_TYPE = installer_type
- CONST.INSTALLER_IP = installer_ip
- cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
- self.openstack_creds,
+ CONST.__setattr__('INSTALLER_TYPE', installer_type)
+ CONST.__setattr__('INSTALLER_IP', installer_ip)
+ cmd = ("fetch_os_creds.sh -d %s -i %s -a %s"
+ % (self.openstack_creds,
installer_type,
installer_ip))
self.cli_os.openstack_creds = self.openstack_creds
@@ -144,8 +138,9 @@ class CliOpenStackTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
def test_check(self, mock_ftutils_execute):
with mock.patch.object(self.cli_os, 'ping_endpoint'):
- CONST.dir_repo_functest = self.dir_repo_functest
- cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh"
+ CONST.__setattr__('dir_repo_functest', self.dir_repo_functest)
+ cmd = os.path.join(CONST.__getattribute__('dir_repo_functest'),
+ "functest/ci/check_os.sh")
self.cli_os.check()
mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
@@ -235,4 +230,5 @@ class CliOpenStackTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/commands/test_cli_testcase.py b/functest/tests/unit/cli/commands/test_cli_testcase.py
index 39c8139d7..fddfc3173 100644
--- a/functest/tests/unit/cli/commands/test_cli_testcase.py
+++ b/functest/tests/unit/cli/commands/test_cli_testcase.py
@@ -17,8 +17,6 @@ from functest.utils.constants import CONST
class CliTestCasesTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.testname = 'testname'
with mock.patch('functest.cli.commands.cli_testcase.tb'):
@@ -42,7 +40,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_default(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n -r ", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n -r ", self.testname))
self.cli_tests.run(self.testname, noclean=True, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -51,7 +51,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_noclean_missing_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n ", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n ", self.testname))
self.cli_tests.run(self.testname, noclean=True, report=False)
mock_ft_utils.assert_called_with(cmd)
@@ -60,7 +62,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_report_missing_noclean(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-r ", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-r ", self.testname))
self.cli_tests.run(self.testname, noclean=False, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -69,7 +73,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_missing_noclean_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "", self.testname))
self.cli_tests.run(self.testname, noclean=False, report=False)
mock_ft_utils.assert_called_with(cmd)
@@ -100,4 +106,5 @@ class CliTestCasesTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/commands/test_cli_tier.py b/functest/tests/unit/cli/commands/test_cli_tier.py
index 802359f16..550eec931 100644
--- a/functest/tests/unit/cli/commands/test_cli_tier.py
+++ b/functest/tests/unit/cli/commands/test_cli_tier.py
@@ -17,8 +17,6 @@ from functest.utils.constants import CONST
class CliTierTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.tiername = 'tiername'
self.testnames = 'testnames'
@@ -90,8 +88,9 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_default(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n -r ",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n -r ", self.tiername))
self.cli_tier.run(self.tiername, noclean=True, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -100,8 +99,9 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_report_missing_noclean(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-r ",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-r ", self.tiername))
self.cli_tier.run(self.tiername, noclean=False, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -110,8 +110,9 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_noclean_missing_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n ",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n ", self.tiername))
self.cli_tier.run(self.tiername, noclean=True, report=False)
mock_ft_utils.assert_called_with(cmd)
@@ -120,11 +121,13 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_missing_noclean_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "", self.tiername))
self.cli_tier.run(self.tiername, noclean=False, report=False)
mock_ft_utils.assert_called_with(cmd)
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/test_cli_base.py b/functest/tests/unit/cli/test_cli_base.py
index fe065c2aa..896032795 100644
--- a/functest/tests/unit/cli/test_cli_base.py
+++ b/functest/tests/unit/cli/test_cli_base.py
@@ -22,8 +22,6 @@ with mock.patch('functest.cli.commands.cli_testcase.CliTestcase.__init__',
class CliBaseTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.runner = CliRunner()
self._openstack = cli_base._openstack
@@ -135,4 +133,5 @@ class CliBaseTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_feature.py b/functest/tests/unit/core/test_feature.py
index 8de42ec50..0160c8e16 100644
--- a/functest/tests/unit/core/test_feature.py
+++ b/functest/tests/unit/core/test_feature.py
@@ -17,10 +17,6 @@ import mock
from functest.core import feature
from functest.core import testcase
-# logging must be disabled else it calls time.time()
-# what will break these unit tests.
-logging.disable(logging.CRITICAL)
-
class FeatureTestingBase(unittest.TestCase):
@@ -95,4 +91,7 @@ class BashFeatureTesting(FeatureTestingBase):
if __name__ == "__main__":
+ # logging must be disabled else it calls time.time()
+ # what will break these unit tests.
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_pytest_suite_runner.py b/functest/tests/unit/core/test_pytest_suite_runner.py
deleted file mode 100644
index 15e5bd73b..000000000
--- a/functest/tests/unit/core/test_pytest_suite_runner.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/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 functest.core import pytest_suite_runner
-from functest.core import testcase
-
-
-class PyTestSuiteRunnerTesting(unittest.TestCase):
-
- logging.disable(logging.CRITICAL)
-
- def setUp(self):
- self.psrunner = pytest_suite_runner.PyTestSuiteRunner()
- self.result = mock.Mock()
- attrs = {'errors': [('test1', 'error_msg1')],
- 'failures': [('test2', 'failure_msg1')]}
- self.result.configure_mock(**attrs)
-
- self.pass_results = mock.Mock()
- attrs = {'errors': None,
- 'failures': None}
- self.pass_results.configure_mock(**attrs)
-
- def test_run(self):
- self.psrunner.case_name = 'test_case_name'
- with mock.patch('functest.core.pytest_suite_runner.'
- 'unittest.TextTestRunner.run',
- return_value=self.result):
- self.assertEqual(self.psrunner.run(),
- testcase.TestCase.EX_OK)
-
- with mock.patch('functest.core.pytest_suite_runner.'
- 'unittest.TextTestRunner.run',
- return_value=self.pass_results):
- self.assertEqual(self.psrunner.run(),
- testcase.TestCase.EX_OK)
-
-
-if __name__ == "__main__":
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_testcase.py b/functest/tests/unit/core/test_testcase.py
index 2adf4a6dc..ef0983cc0 100644
--- a/functest/tests/unit/core/test_testcase.py
+++ b/functest/tests/unit/core/test_testcase.py
@@ -23,8 +23,6 @@ class TestCaseTesting(unittest.TestCase):
"""The class testing TestCase."""
# pylint: disable=missing-docstring,too-many-public-methods
- logging.disable(logging.CRITICAL)
-
_case_name = "base"
_project_name = "functest"
_published_result = "PASS"
@@ -225,4 +223,5 @@ class TestCaseTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_unit.py b/functest/tests/unit/core/test_unit.py
new file mode 100644
index 000000000..f86ea8d31
--- /dev/null
+++ b/functest/tests/unit/core/test_unit.py
@@ -0,0 +1,90 @@
+#!/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 functest.core import unit
+from functest.core import testcase
+
+
+class PyTestSuiteRunnerTesting(unittest.TestCase):
+
+ def setUp(self):
+ self.psrunner = unit.Suite()
+
+ @mock.patch('unittest.TestLoader')
+ def _test_run(self, mock_class=None, result=mock.Mock(),
+ status=testcase.TestCase.EX_OK):
+ with mock.patch('functest.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(self.psrunner.suite, None)
+
+ 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': [], 'failures': []})
+ 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': [('test1', 'error_msg1')],
+ 'failures': [('test2', 'failure_msg1')]})
+ 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': [], 'failures': []})
+ 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('functest.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/functest/tests/unit/core/test_vnf.py b/functest/tests/unit/core/test_vnf.py
index 793e95768..ce8590400 100644
--- a/functest/tests/unit/core/test_vnf.py
+++ b/functest/tests/unit/core/test_vnf.py
@@ -21,8 +21,6 @@ from functest.core import testcase
class VnfBaseTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.test = vnf.VnfOnBoarding(
project='functest', case_name='aaa')
@@ -148,12 +146,12 @@ class VnfBaseTesting(unittest.TestCase):
def test_deploy_vnf_unimplemented(self):
with self.assertRaises(Exception) as context:
self.test.deploy_vnf()
- self.assertTrue('VNF not deployed' in context.exception)
+ self.assertIn('VNF not deployed', str(context.exception))
def test_test_vnf_unimplemented(self):
with self.assertRaises(Exception) as context:
self.test.test_vnf()()
- self.assertTrue('VNF not tested' in context.exception)
+ self.assertIn('VNF not tested', str(context.exception))
def test_parse_results_ex_ok(self):
self.test.details['test_vnf']['status'] = 'PASS'
@@ -165,4 +163,5 @@ class VnfBaseTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/energy/test_functest_energy.py b/functest/tests/unit/energy/test_functest_energy.py
index ffe044bc2..6387b97ba 100644
--- a/functest/tests/unit/energy/test_functest_energy.py
+++ b/functest/tests/unit/energy/test_functest_energy.py
@@ -19,8 +19,6 @@ import functest.energy.energy as energy
CASE_NAME = "UNIT_test_CASE"
STEP_NAME = "UNIT_test_STEP"
-logging.disable(logging.CRITICAL)
-
class MockHttpResponse(object): # pylint: disable=too-few-public-methods
"""Mock response for Energy recorder API."""
@@ -274,4 +272,5 @@ class EnergyRecorderTest(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/features/test_barometer.py b/functest/tests/unit/features/test_barometer.py
index 8ca463b24..8c2585d9c 100644
--- a/functest/tests/unit/features/test_barometer.py
+++ b/functest/tests/unit/features/test_barometer.py
@@ -16,15 +16,12 @@ import unittest
import mock
from functest.core import testcase
-sys.modules['baro_tests'] = mock.Mock() # noqa
-# pylint: disable=wrong-import-position
-from functest.opnfv_tests.features import barometer
+with mock.patch('functest.utils.functest_utils.get_parameter_from_yaml'):
+ from functest.opnfv_tests.features import barometer
class BarometerTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
_case_name = "barometercollectd"
_project_name = "barometer"
@@ -47,4 +44,5 @@ class BarometerTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/odl/test_odl.py b/functest/tests/unit/odl/test_odl.py
index e2778e249..60adf211d 100644
--- a/functest/tests/unit/odl/test_odl.py
+++ b/functest/tests/unit/odl/test_odl.py
@@ -32,8 +32,6 @@ class ODLVisitorTesting(unittest.TestCase):
"""The class testing ODLResultVisitor."""
# pylint: disable=missing-docstring
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.visitor = odl.ODLResultVisitor()
@@ -312,8 +310,6 @@ class ODLMainTesting(ODLTesting):
def test_run_ko(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
self.assertRaises(RobotError):
self._test_main(testcase.TestCase.EX_RUN_ERROR, *args)
@@ -322,71 +318,33 @@ class ODLMainTesting(ODLTesting):
def test_parse_results_ko(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
mock.patch.object(self.test, 'parse_results',
side_effect=RobotError):
self._test_main(testcase.TestCase.EX_RUN_ERROR, *args)
- @mock.patch('os.remove', side_effect=Exception)
- @mock.patch('robot.run')
- @mock.patch('os.makedirs')
- def test_remove_exc(self, *args):
- with mock.patch.object(self.test, 'set_robotframework_vars',
- return_value=True), \
- mock.patch.object(self.test, 'parse_results'), \
- self.assertRaises(Exception):
- self._test_main(testcase.TestCase.EX_OK, *args)
-
- @mock.patch('os.remove')
@mock.patch('robot.run')
@mock.patch('os.makedirs')
def test_ok(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
mock.patch.object(self.test, 'parse_results'):
self._test_main(testcase.TestCase.EX_OK, *args)
- @mock.patch('os.remove')
@mock.patch('robot.run')
@mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, ''))
def test_makedirs_oserror17(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True) as mock_open, \
mock.patch.object(self.test, 'parse_results'):
self._test_main(testcase.TestCase.EX_OK, *args)
- mock_open.assert_called_once_with(
- os.path.join(odl.ODLTests.res_dir, 'stdout.txt'), 'w+')
- @mock.patch('os.remove')
@mock.patch('robot.run', return_value=1)
@mock.patch('os.makedirs')
def test_testcases_in_failure(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True) as mock_open, \
mock.patch.object(self.test, 'parse_results'):
self._test_main(testcase.TestCase.EX_OK, *args)
- mock_open.assert_called_once_with(
- os.path.join(odl.ODLTests.res_dir, 'stdout.txt'), 'w+')
-
- @mock.patch('os.remove', side_effect=OSError)
- @mock.patch('robot.run')
- @mock.patch('os.makedirs')
- def test_remove_oserror(self, *args):
- with mock.patch.object(self.test, 'set_robotframework_vars',
- return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True) as mock_open, \
- mock.patch.object(self.test, 'parse_results'):
- self._test_main(testcase.TestCase.EX_OK, *args)
- mock_open.assert_called_once_with(
- os.path.join(odl.ODLTests.res_dir, 'stdout.txt'), 'w+')
class ODLRunTesting(ODLTesting):
@@ -636,4 +594,5 @@ class ODLArgParserTesting(ODLTesting):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/rally/test_rally.py b/functest/tests/unit/openstack/rally/test_rally.py
index c78286186..b9e786162 100644
--- a/functest/tests/unit/openstack/rally/test_rally.py
+++ b/functest/tests/unit/openstack/rally/test_rally.py
@@ -19,8 +19,6 @@ from functest.utils.constants import CONST
class OSRallyTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.nova_client = mock.Mock()
self.neutron_client = mock.Mock()
@@ -39,7 +37,7 @@ class OSRallyTesting(unittest.TestCase):
self.polling_iter = 2
def test_build_task_args_missing_floating_network(self):
- CONST.OS_AUTH_URL = None
+ CONST.__setattr__('OS_AUTH_URL', None)
with mock.patch('functest.opnfv_tests.openstack.rally.rally.'
'os_utils.get_external_net',
return_value=None):
@@ -47,7 +45,7 @@ class OSRallyTesting(unittest.TestCase):
self.assertEqual(task_args['floating_network'], '')
def test_build_task_args_missing_net_id(self):
- CONST.OS_AUTH_URL = None
+ CONST.__setattr__('OS_AUTH_URL', None)
self.rally_base.network_dict['net_id'] = ''
with mock.patch('functest.opnfv_tests.openstack.rally.rally.'
'os_utils.get_external_net',
@@ -56,7 +54,7 @@ class OSRallyTesting(unittest.TestCase):
self.assertEqual(task_args['netid'], '')
def test_build_task_args_missing_auth_url(self):
- CONST.OS_AUTH_URL = None
+ CONST.__setattr__('OS_AUTH_URL', None)
with mock.patch('functest.opnfv_tests.openstack.rally.rally.'
'os_utils.get_external_net',
return_value='test_floating_network'):
@@ -136,8 +134,8 @@ class OSRallyTesting(unittest.TestCase):
'lineline')
def test_excl_scenario_default(self):
- CONST.INSTALLER_TYPE = 'test_installer'
- CONST.DEPLOY_SCENARIO = 'test_scenario'
+ CONST.__setattr__('INSTALLER_TYPE', 'test_installer')
+ CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
dic = {'scenario': [{'scenarios': ['test_scenario'],
'installers': ['test_installer'],
'tests': ['test']}]}
@@ -154,8 +152,8 @@ class OSRallyTesting(unittest.TestCase):
[])
def test_excl_func_default(self):
- CONST.INSTALLER_TYPE = 'test_installer'
- CONST.DEPLOY_SCENARIO = 'test_scenario'
+ CONST.__setattr__('INSTALLER_TYPE', 'test_installer')
+ CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
dic = {'functionality': [{'functions': ['no_live_migration'],
'tests': ['test']}]}
with mock.patch('__builtin__.open', mock.mock_open()), \
@@ -375,4 +373,5 @@ class OSRallyTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/refstack_client/test_refstack_client.py b/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
index 60e180c9e..8c149baa8 100644
--- a/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
+++ b/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
@@ -17,11 +17,12 @@ from functest.utils.constants import CONST
class OSRefstackClientTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
- _config = \
- os.path.join(CONST.dir_functest_test, CONST.refstack_tempest_conf_path)
- _testlist = \
- os.path.join(CONST.dir_functest_test, CONST.refstack_defcore_list)
+ _config = os.path.join(
+ CONST.__getattribute__('dir_functest_test'),
+ CONST.__getattribute__('refstack_tempest_conf_path'))
+ _testlist = os.path.join(
+ CONST.__getattribute__('dir_functest_test'),
+ CONST.__getattribute__('refstack_defcore_list'))
def setUp(self):
self.defaultargs = {'config': self._config,
@@ -29,12 +30,13 @@ class OSRefstackClientTesting(unittest.TestCase):
self.refstackclient = refstack_client.RefstackClient()
def test_source_venv(self):
- CONST.dir_refstack_client = 'test_repo_dir'
+ CONST.__setattr__('dir_refstack_client', 'test_repo_dir')
with mock.patch('functest.opnfv_tests.openstack.refstack_client.'
'refstack_client.ft_utils.execute_command') as m:
cmd = ("cd {0};"
". .venv/bin/activate;"
- "cd -;".format(CONST.dir_refstack_client))
+ "cd -;"
+ .format(CONST.__getattribute__('dir_refstack_client')))
self.refstackclient.source_venv()
m.assert_any_call(cmd)
@@ -45,9 +47,10 @@ class OSRefstackClientTesting(unittest.TestCase):
'refstack_client.ft_utils.execute_command') as m:
cmd = ("cd {0};"
"./refstack-client test -c {1} -v --test-list {2};"
- "cd -;".format(CONST.dir_refstack_client,
- config,
- testlist))
+ "cd -;"
+ .format(CONST.__getattribute__('dir_refstack_client'),
+ config,
+ testlist))
self.refstackclient.run_defcore(config, testlist)
m.assert_any_call(cmd)
@@ -63,7 +66,7 @@ class OSRefstackClientTesting(unittest.TestCase):
self.assertEqual(self.refstackclient.main(**kwargs), status)
if len(args) > 0:
args[0].assert_called_once_with(
- refstack_client.RefstackClient.result_dir)
+ refstack_client.RefstackClient.result_dir)
if len(args) > 1:
args
@@ -101,4 +104,5 @@ class OSRefstackClientTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/tempest/test_conf_utils.py b/functest/tests/unit/openstack/tempest/test_conf_utils.py
index 8ca5cc5b6..23f6e45c7 100644
--- a/functest/tests/unit/openstack/tempest/test_conf_utils.py
+++ b/functest/tests/unit/openstack/tempest/test_conf_utils.py
@@ -16,8 +16,6 @@ from functest.utils.constants import CONST
class OSTempestConfUtilsTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def test_create_tempest_resources_missing_network_dic(self):
with mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
'os_utils.get_keystone_client',
@@ -54,12 +52,12 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
return_value=(mock.Mock(), None)), \
self.assertRaises(Exception) as context:
- CONST.tempest_use_custom_images = True
+ CONST.__setattr__('tempest_use_custom_images', True)
conf_utils.create_tempest_resources()
msg = 'Failed to create image'
self.assertTrue(msg in context)
- CONST.tempest_use_custom_images = False
+ CONST.__setattr__('tempest_use_custom_images', False)
conf_utils.create_tempest_resources(use_custom_images=True)
msg = 'Failed to create image'
self.assertTrue(msg in context)
@@ -84,20 +82,20 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
'os_utils.get_or_create_flavor',
return_value=(mock.Mock(), None)), \
self.assertRaises(Exception) as context:
- CONST.tempest_use_custom_images = True
- CONST.tempest_use_custom_flavors = True
+ CONST.__setattr__('tempest_use_custom_images', True)
+ CONST.__setattr__('tempest_use_custom_flavors', True)
conf_utils.create_tempest_resources()
msg = 'Failed to create flavor'
self.assertTrue(msg in context)
- CONST.tempest_use_custom_images = True
- CONST.tempest_use_custom_flavors = False
+ CONST.__setattr__('tempest_use_custom_images', True)
+ CONST.__setattr__('tempest_use_custom_flavors', False)
conf_utils.create_tempest_resources(use_custom_flavors=False)
msg = 'Failed to create flavor'
self.assertTrue(msg in context)
def test_get_verifier_id_missing_verifier(self):
- CONST.tempest_deployment_name = 'test_deploy_name'
+ CONST.__setattr__('tempest_deployment_name', 'test_deploy_name')
with mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.subprocess.Popen') as mock_popen, \
self.assertRaises(Exception):
@@ -108,7 +106,7 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
conf_utils.get_verifier_id(),
def test_get_verifier_id_default(self):
- CONST.tempest_deployment_name = 'test_deploy_name'
+ CONST.__setattr__('tempest_deployment_name', 'test_deploy_name')
with mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.subprocess.Popen') as mock_popen:
mock_stdout = mock.Mock()
@@ -120,7 +118,7 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
'test_deploy_id')
def test_get_verifier_deployment_id_missing_rally(self):
- CONST.rally_deployment_name = 'test_rally_deploy_name'
+ CONST.__setattr__('tempest_deployment_name', 'test_deploy_name')
with mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.subprocess.Popen') as mock_popen, \
self.assertRaises(Exception):
@@ -131,7 +129,7 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
conf_utils.get_verifier_deployment_id(),
def test_get_verifier_deployment_id_default(self):
- CONST.rally_deployment_name = 'test_rally_deploy_name'
+ CONST.__setattr__('tempest_deployment_name', 'test_deploy_name')
with mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.subprocess.Popen') as mock_popen:
mock_stdout = mock.Mock()
@@ -240,8 +238,8 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
mock.patch('__builtin__.open', mock.mock_open()), \
mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.shutil.copyfile'):
- CONST.dir_functest_test = 'test_dir'
- CONST.refstack_tempest_conf_path = 'test_path'
+ CONST.__setattr__('dir_functest_test', 'test_dir')
+ CONST.__setattr__('refstack_tempest_conf_path', 'test_path')
conf_utils.configure_tempest_defcore('test_dep_dir',
img_flavor_dict)
mset.assert_any_call('compute', 'image_ref', 'test_image_id')
@@ -266,8 +264,8 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
mock.patch('__builtin__.open', mock.mock_open()), \
mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.backup_tempest_config'):
- CONST.dir_functest_test = 'test_dir'
- CONST.OS_ENDPOINT_TYPE = None
+ CONST.__setattr__('dir_functest_test', 'test_dir')
+ CONST.__setattr__('OS_ENDPOINT_TYPE', None)
conf_utils.\
configure_tempest_update_params('test_conf_file',
IMAGE_ID=image_id,
@@ -277,25 +275,25 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
self.assertTrue(mwrite.called)
def test_configure_tempest_update_params_missing_image_id(self):
- CONST.tempest_use_custom_images = True
+ CONST.__setattr__('tempest_use_custom_images', True)
self._test_missing_param(('compute', 'image_ref',
'test_image_id'), 'test_image_id',
None)
def test_configure_tempest_update_params_missing_image_id_alt(self):
- CONST.tempest_use_custom_images = True
+ CONST.__setattr__('tempest_use_custom_images', True)
conf_utils.IMAGE_ID_ALT = 'test_image_id_alt'
self._test_missing_param(('compute', 'image_ref_alt',
'test_image_id_alt'), None, None)
def test_configure_tempest_update_params_missing_flavor_id(self):
- CONST.tempest_use_custom_flavors = True
+ CONST.__setattr__('tempest_use_custom_flavors', True)
self._test_missing_param(('compute', 'flavor_ref',
'test_flavor_id'), None,
'test_flavor_id')
def test_configure_tempest_update_params_missing_flavor_id_alt(self):
- CONST.tempest_use_custom_flavors = True
+ CONST.__setattr__('tempest_use_custom_flavors', True)
conf_utils.FLAVOR_ID_ALT = 'test_flavor_id_alt'
self._test_missing_param(('compute', 'flavor_ref_alt',
'test_flavor_id_alt'), None,
@@ -371,4 +369,5 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
mexe.assert_called_once_with(cmd, error_msg=error_msg)
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py
index bb75c9ed7..b8b258b36 100644
--- a/functest/tests/unit/openstack/tempest/test_tempest.py
+++ b/functest/tests/unit/openstack/tempest/test_tempest.py
@@ -18,8 +18,6 @@ from functest.utils.constants import CONST
class OSTempestTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'conf_utils.get_verifier_id',
@@ -114,8 +112,8 @@ class OSTempestTesting(unittest.TestCase):
mock.patch.object(self.tempestcommon, 'read_file',
return_value=['test1', 'test2']):
conf_utils.TEMPEST_BLACKLIST = Exception
- CONST.INSTALLER_TYPE = 'installer_type'
- CONST.DEPLOY_SCENARIO = 'deploy_scenario'
+ CONST.__setattr__('INSTALLER_TYPE', 'installer_type')
+ CONST.__setattr__('DEPLOY_SCENARIO', 'deploy_scenario')
self.tempestcommon.apply_tempest_blacklist()
obj = m()
obj.write.assert_any_call('test1\n')
@@ -130,8 +128,8 @@ class OSTempestTesting(unittest.TestCase):
return_value=['test1', 'test2']), \
mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'yaml.safe_load', return_value=item_dict):
- CONST.INSTALLER_TYPE = 'installer_type'
- CONST.DEPLOY_SCENARIO = 'deploy_scenario'
+ CONST.__setattr__('INSTALLER_TYPE', 'installer_type')
+ CONST.__setattr__('DEPLOY_SCENARIO', 'deploy_scenario')
self.tempestcommon.apply_tempest_blacklist()
obj = m()
obj.write.assert_any_call('test1\n')
@@ -230,4 +228,5 @@ class OSTempestTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/test_logging.ini b/functest/tests/unit/test_logging.ini
deleted file mode 100644
index 492767d16..000000000
--- a/functest/tests/unit/test_logging.ini
+++ /dev/null
@@ -1,27 +0,0 @@
-[loggers]
-keys=root,functest_logger
-
-[logger_root]
-level=DEBUG
-handlers=console
-
-[logger_functest_logger]
-level=DEBUG
-handlers=console
-qualname=functest.utils.functest_logger
-propagate=0
-
-[handlers]
-keys=console
-
-[handler_console]
-class=StreamHandler
-level=INFO
-formatter=standard
-args=(sys.stdout,)
-
-[formatters]
-keys=standard
-
-[formatter_standard]
-format=%(asctime)s - %(name)s - %(levelname)s - %(message)s \ No newline at end of file
diff --git a/functest/tests/unit/utils/test_decorators.py b/functest/tests/unit/utils/test_decorators.py
index f8bd9a54f..44448f238 100644
--- a/functest/tests/unit/utils/test_decorators.py
+++ b/functest/tests/unit/utils/test_decorators.py
@@ -32,8 +32,6 @@ URL = 'file://{}'.format(FILE)
class DecoratorsTesting(unittest.TestCase):
# pylint: disable=missing-docstring
- logging.disable(logging.CRITICAL)
-
_case_name = 'base'
_project_name = 'functest'
_start_time = 1.0
@@ -65,7 +63,7 @@ class DecoratorsTesting(unittest.TestCase):
'pod_name': self._node_name, 'installer': self._installer_type,
'scenario': self._deploy_scenario, 'version': VERSION,
'details': {}, 'criteria': self._result}
- return json.dumps(data)
+ return json.dumps(data, sort_keys=True)
@mock.patch('{}.get_db_url'.format(functest_utils.__name__),
return_value='http://127.0.0.1')
@@ -131,5 +129,5 @@ class DecoratorsTesting(unittest.TestCase):
if __name__ == "__main__":
- logging.basicConfig()
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py
index 57e0c465d..12604c1a0 100644
--- a/functest/tests/unit/utils/test_functest_utils.py
+++ b/functest/tests/unit/utils/test_functest_utils.py
@@ -23,8 +23,6 @@ from functest.utils import functest_utils
class FunctestUtilsTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.url = 'http://www.opnfv.org/'
self.timeout = 5
@@ -57,7 +55,8 @@ class FunctestUtilsTesting(unittest.TestCase):
self.testcase_dict = {'case_name': 'testname',
'criteria': self.criteria}
self.parameter = 'general.openstack.image_name'
- self.config_yaml = 'test_config_yaml-'
+ self.config_yaml = os.path.normpath(os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), '../../../ci/config_functest.yaml'))
self.db_url_env = 'http://foo/testdb'
self.file_yaml = {'general': {'openstack': {'image_name':
'test_image_name'}}}
@@ -453,9 +452,8 @@ class FunctestUtilsTesting(unittest.TestCase):
mock_logger_info.assert_called_once_with(msg_exec)
mopen.assert_called_once_with(self.output_file, "w")
- @mock.patch('functest.utils.functest_utils.logger.info')
- def test_execute_command_args_missing_with_success(self, mock_logger_info,
- ):
+ @mock.patch('sys.stdout')
+ def test_execute_command_args_missing_with_success(self, stdout=None):
with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
as mock_subproc_open:
@@ -477,9 +475,8 @@ class FunctestUtilsTesting(unittest.TestCase):
output_file=None)
self.assertEqual(resp, 0)
- @mock.patch('functest.utils.functest_utils.logger.error')
- def test_execute_command_args_missing_with_error(self, mock_logger_error,
- ):
+ @mock.patch('sys.stdout')
+ def test_execute_command_args_missing_with_error(self, stdout=None):
with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
as mock_subproc_open:
@@ -587,4 +584,5 @@ class FunctestUtilsTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_openstack_clean.py b/functest/tests/unit/utils/test_openstack_clean.py
index 156695380..fe7b50d45 100644
--- a/functest/tests/unit/utils/test_openstack_clean.py
+++ b/functest/tests/unit/utils/test_openstack_clean.py
@@ -15,8 +15,6 @@ from functest.tests.unit import test_utils
class OSCleanTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def _get_instance(self, key):
mock_obj = mock.Mock()
attrs = {'id': 'id' + str(key), 'name': 'name' + str(key),
@@ -723,4 +721,5 @@ class OSCleanTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_openstack_snapshot.py b/functest/tests/unit/utils/test_openstack_snapshot.py
index 52744db1c..d3f93994d 100644
--- a/functest/tests/unit/utils/test_openstack_snapshot.py
+++ b/functest/tests/unit/utils/test_openstack_snapshot.py
@@ -14,8 +14,6 @@ from functest.utils import openstack_snapshot
class OSTackerTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def _get_instance(self, key):
mock_obj = mock.Mock()
attrs = {'id': 'id' + str(key), 'name': 'name' + str(key),
@@ -232,4 +230,5 @@ class OSTackerTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_openstack_tacker.py b/functest/tests/unit/utils/test_openstack_tacker.py
index 37d77a18f..3c0fc3d0d 100644
--- a/functest/tests/unit/utils/test_openstack_tacker.py
+++ b/functest/tests/unit/utils/test_openstack_tacker.py
@@ -17,8 +17,6 @@ from functest.tests.unit import test_utils
class OSTackerTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.tacker_client = mock.Mock()
self.getresponse = {'vnfds': [{'id': 'test_id'}],
@@ -522,4 +520,5 @@ class OSTackerTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py
index a7df264c9..15b540577 100644
--- a/functest/tests/unit/utils/test_openstack_utils.py
+++ b/functest/tests/unit/utils/test_openstack_utils.py
@@ -17,8 +17,6 @@ from functest.utils import openstack_utils
class OSUtilsTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def _get_env_cred_dict(self, os_prefix=''):
return {'OS_USERNAME': os_prefix + 'username',
'OS_PASSWORD': os_prefix + 'password',
@@ -1839,4 +1837,5 @@ class OSUtilsTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/vnf/ims/test_clearwater.py b/functest/tests/unit/vnf/ims/test_clearwater.py
index 18bebfdff..bc31c33e0 100644
--- a/functest/tests/unit/vnf/ims/test_clearwater.py
+++ b/functest/tests/unit/vnf/ims/test_clearwater.py
@@ -16,8 +16,6 @@ from functest.opnfv_tests.vnf.ims import orchestrator_cloudify
class ClearwaterTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.clearwater = clearwater.Clearwater()
self.orchestrator = orchestrator_cloudify.Orchestrator('test_dir')
@@ -83,4 +81,5 @@ class ClearwaterTesting(unittest.TestCase):
'test_domain')
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/vnf/ims/test_cloudify_ims.py b/functest/tests/unit/vnf/ims/test_cloudify_ims.py
index f47ea865e..c3c04e1d9 100644
--- a/functest/tests/unit/vnf/ims/test_cloudify_ims.py
+++ b/functest/tests/unit/vnf/ims/test_cloudify_ims.py
@@ -15,8 +15,6 @@ from functest.opnfv_tests.vnf.ims import cloudify_ims
class CloudifyImsTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
with mock.patch('functest.opnfv_tests.vnf.ims.cloudify_ims.'
'os.makedirs'), \
@@ -491,4 +489,5 @@ class CloudifyImsTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/vnf/ims/test_ims_base.py b/functest/tests/unit/vnf/ims/test_ims_base.py
index e283199c3..db5b18d71 100644
--- a/functest/tests/unit/vnf/ims/test_ims_base.py
+++ b/functest/tests/unit/vnf/ims/test_ims_base.py
@@ -15,8 +15,6 @@ from functest.opnfv_tests.vnf.ims import clearwater_ims_base as ims_base
class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
with mock.patch('functest.opnfv_tests.vnf.ims.cloudify_ims.'
'os.makedirs'):
@@ -55,4 +53,5 @@ class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py b/functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py
index bf6d483f7..570646644 100644
--- a/functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py
+++ b/functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py
@@ -16,8 +16,6 @@ from functest.opnfv_tests.vnf.ims import orchestrator_cloudify
class ImsVnfTesting(unittest.TestCase):
- logging.disable(logging.CRITICAL)
-
def setUp(self):
self.orchestrator = orchestrator_cloudify.Orchestrator('test_dir')
self.bp = {'file_name': 'test_file',
@@ -174,4 +172,5 @@ class ImsVnfTesting(unittest.TestCase):
'test_subnet')
if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/utils/env.py b/functest/utils/env.py
index c9629e153..3724ec998 100644
--- a/functest/utils/env.py
+++ b/functest/utils/env.py
@@ -15,7 +15,9 @@ default_envs = {
'INSTALLER_IP': None,
'BUILD_TAG': None,
'OS_ENDPOINT_TYPE': None,
- 'OS_AUTH_URL': None
+ 'OS_AUTH_URL': None,
+ 'CONFIG_FUNCTEST_YAML': os.path.normpath(os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), '../ci/config_functest.yaml'))
}
diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py
index bf30f56ee..dc20eea10 100644
--- a/functest/utils/functest_utils.py
+++ b/functest/utils/functest_utils.py
@@ -24,6 +24,7 @@ from six.moves import urllib
import yaml
from git import Repo
+from functest.utils import constants
from functest.utils import decorators
logger = logging.getLogger(__name__)
@@ -220,7 +221,8 @@ def push_results_to_db(project, case_name,
error = None
headers = {'Content-Type': 'application/json'}
try:
- r = requests.post(url, data=json.dumps(params), headers=headers)
+ r = requests.post(url, data=json.dumps(params, sort_keys=True),
+ headers=headers)
logger.debug(r)
r.raise_for_status()
except requests.RequestException as exc:
@@ -375,7 +377,7 @@ def get_parameter_from_yaml(parameter, file):
def get_functest_config(parameter):
- yaml_ = os.environ["CONFIG_FUNCTEST_YAML"]
+ yaml_ = constants.CONST.__getattribute__('CONFIG_FUNCTEST_YAML')
return get_parameter_from_yaml(parameter, yaml_)
@@ -397,7 +399,7 @@ def get_testcases_file_dir():
def get_functest_yaml():
- with open(os.environ["CONFIG_FUNCTEST_YAML"]) as f:
+ with open(constants.CONST.__getattribute__('CONFIG_FUNCTEST_YAML')) as f:
functest_yaml = yaml.safe_load(f)
f.close()
return functest_yaml
diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py
index 8bd950528..57a2aa2be 100644
--- a/functest/utils/openstack_utils.py
+++ b/functest/utils/openstack_utils.py
@@ -1081,10 +1081,10 @@ def check_security_group_rules(neutron_client, sg_id, direction, protocol,
try:
security_rules = get_security_group_rules(neutron_client, sg_id)
security_rules = [rule for rule in security_rules
- if (rule["direction"].lower() == direction
- and rule["protocol"].lower() == protocol
- and rule["port_range_min"] == port_min
- and rule["port_range_max"] == port_max)]
+ if (rule["direction"].lower() == direction and
+ rule["protocol"].lower() == protocol and
+ rule["port_range_min"] == port_min and
+ rule["port_range_max"] == port_max)]
if len(security_rules) == 0:
return True
else:
diff --git a/requirements.py3.txt b/requirements.py3.txt
new file mode 100644
index 000000000..6a003d532
--- /dev/null
+++ b/requirements.py3.txt
@@ -0,0 +1,39 @@
+#
+#
+# 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
+#
+pyyaml==3.10
+gitpython==1.0.1
+python-openstackclient==2.3.0
+python-ceilometerclient==2.6.2
+python-heatclient==1.7.0
+python-keystoneclient==3.5.0
+python-neutronclient==6.0.0
+python-novaclient==6.0.0
+python-congressclient==1.5.0
+python-tackerclient==0.7.0
+pexpect==4.0
+requests==2.9.1
+robotframework==3.0.2
+robotframework-httplibrary==0.4.2
+robotframework-requests==0.4.7
+jmespath==0.9.2
+configObj==5.0.6
+Flask==0.10.1
+xmltodict==0.9.2
+scp==0.10.2
+paramiko==2.1.2
+shyaml
+dnspython
+Pillow==3.3.0
+click==6.6
+openbaton-cli==2.2.1-beta7
+mock==1.3.0
+iniparse==0.4
+PrettyTable>=0.7.1,<0.8 # BSD
+six>=1.9.0 # MIT
+git+https://gerrit.opnfv.org/gerrit/releng#egg=opnfv&subdirectory=modules
+git+https://gerrit.opnfv.org/gerrit/barometer#egg=baro_tests
diff --git a/requirements.txt b/requirements.txt
index 65b369799..059775deb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -16,7 +16,7 @@ python-novaclient==6.0.0
python-congressclient==1.5.0
python-tackerclient==0.7.0
pexpect==4.0
-requests>=2.8.0
+requests==2.9.1
robotframework==3.0.2
robotframework-httplibrary==0.4.2
robotframework-requests==0.4.7
@@ -37,3 +37,5 @@ mock==1.3.0
iniparse==0.4
PrettyTable>=0.7.1,<0.8 # BSD
six>=1.9.0 # MIT
+git+https://gerrit.opnfv.org/gerrit/releng#egg=opnfv&subdirectory=modules
+git+https://gerrit.opnfv.org/gerrit/barometer#egg=baro_tests
diff --git a/run_unit_tests.sh b/run_unit_tests.sh
deleted file mode 100755
index 86096fabf..000000000
--- a/run_unit_tests.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-set -o errexit
-set -o pipefail
-
-# Either Workspace is set (CI)
-if [ -z $WORKSPACE ]
-then
- WORKSPACE=`pwd`
-fi
-
-
-# ***************
-# Run unit tests
-# ***************
-echo "Running unit tests..."
-
-sudo apt-get install -y build-essential python-dev python-pip
-sudo pip install virtualenv==15.1.0
-
-# start vitual env
-virtualenv $WORKSPACE/functest_venv
-source $WORKSPACE/functest_venv/bin/activate
-
-# install python packages
-pip install --upgrade pip
-pip install -r $WORKSPACE/requirements.txt
-pip install -r $WORKSPACE/test-requirements.txt
-pip install $WORKSPACE
-
-#install releng
-rm -rf releng-unittests
-git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng releng-unittests
-pip install releng-unittests/modules/
-rm -fr releng-unittests
-
-export CONFIG_FUNCTEST_YAML=$(pwd)/functest/ci/config_functest.yaml
-nosetests --with-xunit \
- --with-coverage \
- --cover-tests \
- --cover-package=functest \
- --cover-xml \
- --cover-html \
- --log-config=$(pwd)/functest/tests/unit/test_logging.ini \
- functest/tests/unit
-rc=$?
-
-deactivate
-
-exit $rc
diff --git a/test-requirements.txt b/test-requirements.txt
index b0d4ff8d1..9fe4bc749 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -8,3 +8,6 @@
coverage==4.1
mock==1.3.0
nose==1.3.7
+flake8>=2.5.4,<2.6.0 # MIT
+pylint==1.4.5 # GPLv2
+sphinx!=1.6.1,>=1.5.1 # BSD
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 000000000..bde3a9757
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,43 @@
+[tox]
+envlist = docs,pep8,pylint,py35,py27
+
+[testenv]
+usedevelop = True
+deps =
+ -r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
+commands = nosetests --with-xunit \
+ --with-coverage \
+ --cover-tests \
+ --cover-package=functest \
+ --cover-xml \
+ --cover-html \
+ functest/tests/unit
+
+[testenv:docs]
+basepython = python2.7
+commands = sphinx-build -W -b html docs/api/ docs/api/_build
+
+[testenv:pep8]
+basepython = python2.7
+deps =
+ {[testenv]deps}
+commands = flake8
+
+[testenv:pylint]
+basepython = python2.7
+deps =
+ {[testenv]deps}
+whitelist_externals = bash
+commands = bash -c \
+ "pylint --persistent=n functest | sed -ne '/Raw metrics/,//p'"
+
+[testenv:py35]
+dirs =
+ functest/tests/unit/core
+ functest/tests/unit/odl
+ functest/tests/unit/utils/test_decorators.py
+deps =
+ -r{toxinidir}/requirements.py3.txt
+ -r{toxinidir}/test-requirements.txt
+commands = nosetests {[testenv:py35]dirs}