Add reporting to DB in OpenDaylightTesting
authorCédric Ollivier <cedric.ollivier@orange.com>
Fri, 19 Aug 2016 15:39:50 +0000 (17:39 +0200)
committerCédric Ollivier <cedric.ollivier@orange.com>
Fri, 19 Aug 2016 16:14:26 +0000 (18:14 +0200)
It now relies on Robotframework API instead of parsing output.xml.
The type of critical and elapsedime fields are now bool and int
respectively. start_date and stop_date has been fixed too.

JIRA: FUNCTEST-367

Change-Id: I59f3ad2109345395ccf01a714301a14f9323f088
Signed-off-by: Cédric Ollivier <cedric.ollivier@orange.com>
ci/exec_test.sh
testcases/Controllers/ODL/OpenDaylightTesting.py
testcases/Controllers/ODL/odlreport2db.py [deleted file]

index d788330..d1ac68d 100755 (executable)
@@ -80,21 +80,17 @@ function run_test(){
         ;;
         "odl")
             odl_tests
-            ${FUNCTEST_REPO_DIR}/testcases/Controllers/ODL/OpenDaylightTesting.py \
-                --keystoneip $keystone_ip --neutronip $neutron_ip \
-                --osusername ${OS_USERNAME} --ostenantname ${OS_TENANT_NAME} \
-                --ospassword ${OS_PASSWORD} \
-                --odlip $odl_ip --odlwebport $odl_port
-
-            # push results to the DB in case of CI
             if [[ "$report" == "-r" &&
                   -n "$DEPLOY_SCENARIO" && "$DEPLOY_SCENARIO" != "none" &&
                   -n "$INSTALLER_TYPE" && "$INSTALLER_TYPE" != "none" ]] &&
                env | grep NODE_NAME > /dev/null; then
-                odl_logs="/home/opnfv/functest/results/odl/"
-                odl_path="${FUNCTEST_REPO_DIR}/testcases/Controllers/ODL/"
-                python ${odl_path}/odlreport2db.py -x ${odl_logs}/output.xml
+                args=-p
             fi
+            ${FUNCTEST_REPO_DIR}/testcases/Controllers/ODL/OpenDaylightTesting.py \
+                --keystoneip $keystone_ip --neutronip $neutron_ip \
+                --osusername ${OS_USERNAME} --ostenantname ${OS_TENANT_NAME} \
+                --ospassword ${OS_PASSWORD} \
+                --odlip $odl_ip --odlwebport $odl_port ${args}
         ;;
         "tempest_smoke_serial")
             python ${FUNCTEST_REPO_DIR}/testcases/OpenStack/tempest/run_tempest.py \
index 79e385a..0e38d04 100755 (executable)
@@ -8,8 +8,32 @@ import shutil
 import sys
 
 from robot import run
+from robot.api import ExecutionResult, ResultVisitor
+from robot.utils.robottime import timestamp_to_secs
 
 import functest.utils.functest_logger as ft_logger
+import functest.utils.functest_utils as ft_utils
+
+
+class ODLResultVisitor(ResultVisitor):
+
+    def __init__(self):
+        self._data = []
+
+    def visit_test(self, test):
+        output = {}
+        output['name'] = test.name
+        output['parent'] = test.parent.name
+        output['status'] = test.status
+        output['startime'] = test.starttime
+        output['endtime'] = test.endtime
+        output['critical'] = test.critical
+        output['text'] = test.message
+        output['elapsedtime'] = test.elapsedtime
+        self._data.append(output)
+
+    def get_data(self):
+        return self._data
 
 
 class ODLTestCases:
@@ -18,6 +42,7 @@ class ODLTestCases:
     odl_test_repo = repos + "odl_test/"
     neutron_suite_dir = odl_test_repo + "csit/suites/openstack/neutron/"
     basic_suite_dir = odl_test_repo + "csit/suites/integration/basic/"
+    res_dir = '/home/opnfv/functest/results/odl/'
     logger = ft_logger.Logger("opendaylight").getLogger()
 
     @classmethod
@@ -70,19 +95,18 @@ class ODLTestCases:
         except KeyError as e:
             cls.logger.error("Cannot run ODL testcases. Please check", e)
             return False
-        res_dir = '/home/opnfv/functest/results/odl/'
         if (cls.copy_opnf_testcases() and
                 cls.set_robotframework_vars(odlusername, odlpassword)):
             try:
-                os.makedirs(res_dir)
+                os.makedirs(cls.res_dir)
             except OSError:
                 pass
-            stdout_file = res_dir + 'stdout.txt'
+            stdout_file = cls.res_dir + 'stdout.txt'
             with open(stdout_file, 'w') as stdout:
                 result = run(*dirs, variable=variables,
-                             output=res_dir + 'output.xml',
-                             log=res_dir + 'log.html',
-                             report=res_dir + 'report.html',
+                             output=cls.res_dir + 'output.xml',
+                             log=cls.res_dir + 'log.html',
+                             report=cls.res_dir + 'report.html',
                              stdout=stdout)
 
             with open(stdout_file, 'r') as stdout:
@@ -92,6 +116,24 @@ class ODLTestCases:
         else:
             return False
 
+    @classmethod
+    def push_to_db(cls):
+        result = ExecutionResult(cls.res_dir + 'output.xml')
+        visitor = ODLResultVisitor()
+        result.visit(visitor)
+        start_time = timestamp_to_secs(result.suite.starttime)
+        stop_time = timestamp_to_secs(result.suite.endtime)
+        details = {}
+        details['description'] = result.suite.name
+        details['tests'] = visitor.get_data()
+        if not ft_utils.push_results_to_db(
+                "functest", "odl", None, start_time, stop_time,
+                result.suite.status, details):
+            cls.logger.error("Cannot push ODL results to DB")
+            return False
+        else:
+            return True
+
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser()
@@ -125,5 +167,12 @@ if __name__ == '__main__':
     parser.add_argument('-e', '--odlpassword',
                         help='Password for ODL',
                         default='admin')
+    parser.add_argument('-p', '--pushtodb',
+                        help='Push results to DB',
+                        action='store_true')
+
     args = vars(parser.parse_args())
-    sys.exit(ODLTestCases.run(**args))
+    ODLTestCases.run(**args)
+    if args['pushtodb']:
+        sys.exit(not ODLTestCases.push_to_db())
+    sys.exit(os.EX_OK)
diff --git a/testcases/Controllers/ODL/odlreport2db.py b/testcases/Controllers/ODL/odlreport2db.py
deleted file mode 100644 (file)
index 6b3fb91..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/usr/bin/python
-#
-# Authors:
-# - peter.bandzi@cisco.com
-# - morgan.richomme@orange.com
-#
-# src: Peter Bandzi
-# https://github.com/pbandzi/parse-robot/blob/master/convert_robot_to_json.py
-#
-# 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
-#
-
-import getopt
-import json
-import sys
-import time
-import xmltodict
-
-import functest.utils.functest_utils as functest_utils
-
-
-def usage():
-    print """Usage:
-    python odlreport2db.py --xml=<output.xml> --help
-    -x, --xml   xml file generated by robot test
-    -h, --help  this message
-    """
-    sys.exit(2)
-
-
-def populate_detail(test):
-    detail = {}
-    detail['name'] = test['@name']
-    for x in ['status', 'critical', 'starttime', 'endtime']:
-        detail[x] = test['status']['@' + x]
-    if '#text' in test['status']:
-        detail['text'] = test['status']['#text']
-    return detail
-
-
-def parse_test(tests, details):
-    try:
-        for test in tests:
-            details.append(populate_detail(test))
-    except TypeError:
-        # tests is not iterable
-        details.append(populate_detail(tests))
-    return details
-
-
-def parse_suites(suites):
-    data = {}
-    details = []
-    for suite in suites:
-        a = suite['suite']
-        if type(a) == list:
-            for b in a:
-                data['tests'] = parse_test(b['test'], details)
-        else:
-            data['tests'] = parse_test(a['test'], details)
-
-        # data['details'] = parse_test(suite['test'], details)
-    # suites is not iterable
-    return data
-
-
-def main(argv):
-    xml_file = None
-    try:
-        opts, args = getopt.getopt(argv,
-                                   'x:h',
-                                   ['xml=', 'help'])
-    except getopt.GetoptError:
-        usage()
-
-    for opt, arg in opts:
-        if opt in ('-x', '--xml'):
-            xml_file = arg
-        else:
-            usage()
-
-    if xml_file is None:
-        usage()
-
-    with open(xml_file, "r") as myfile:
-        xml_input = myfile.read().replace('\n', '')
-
-    # dictionary populated with data from xml file
-    all_data = xmltodict.parse(xml_input)['robot']
-
-    try:
-        data = parse_suites(all_data['suite']['suite'])
-        data['description'] = all_data['suite']['@name']
-        data['generator'] = all_data['@generator']
-
-        json.dumps(data, indent=4, separators=(',', ': '))
-
-        # success criteria for ODL = 100% of tests OK
-        status = "FAIL"
-        # TODO as part of the tests are executed before in the bash
-        # start and stoptime have no real meaning
-        start_time = time.time()
-        stop_time = start_time
-        tests_passed = 0
-        tests_failed = 0
-        for v in data['tests']:
-            if v['status'] == "PASS":
-                tests_passed += 1
-            else:
-                tests_failed += 1
-
-        if (tests_failed < 1):
-            status = "PASS"
-
-        functest_utils.push_results_to_db("functest",
-                                          "odl",
-                                          None,
-                                          start_time,
-                                          stop_time,
-                                          status,
-                                          data)
-
-    except:
-        print("Error pushing ODL results into DB '%s'" % sys.exc_info()[0])
-
-
-if __name__ == "__main__":
-    main(sys.argv[1:])