From: Cédric Ollivier Date: Fri, 19 Aug 2016 15:39:50 +0000 (+0200) Subject: Add reporting to DB in OpenDaylightTesting X-Git-Tag: 0.2~1269^2 X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=commitdiff_plain;h=a868e1bb75987119c87112d08a194564d84b53ee;p=functest-xtesting.git Add reporting to DB in OpenDaylightTesting 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 --- diff --git a/ci/exec_test.sh b/ci/exec_test.sh index d7883307..d1ac68df 100755 --- a/ci/exec_test.sh +++ b/ci/exec_test.sh @@ -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 \ diff --git a/testcases/Controllers/ODL/OpenDaylightTesting.py b/testcases/Controllers/ODL/OpenDaylightTesting.py index 79e385a2..0e38d04d 100755 --- a/testcases/Controllers/ODL/OpenDaylightTesting.py +++ b/testcases/Controllers/ODL/OpenDaylightTesting.py @@ -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 index 6b3fb913..00000000 --- a/testcases/Controllers/ODL/odlreport2db.py +++ /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= --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:])