3 # Copyright (c) 2017 Orange and others.
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 """Define classes required to run any Robot suites."""
12 from __future__ import division
19 from robot.errors import RobotError
21 from robot.utils.robottime import timestamp_to_secs
22 from six import StringIO
24 from functest.core import testcase
25 from functest.utils import constants
27 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
30 class ResultVisitor(robot.api.ResultVisitor):
31 """Visitor to get result details."""
36 def visit_test(self, test):
38 output['name'] = test.name
39 output['parent'] = test.parent.name
40 output['status'] = test.status
41 output['starttime'] = test.starttime
42 output['endtime'] = test.endtime
43 output['critical'] = test.critical
44 output['text'] = test.message
45 output['elapsedtime'] = test.elapsedtime
46 self._data.append(output)
49 """Get the details of the result."""
53 class RobotFramework(testcase.TestCase):
54 """RobotFramework runner."""
56 __logger = logging.getLogger(__name__)
58 def __init__(self, **kwargs):
59 self.res_dir = os.path.join(
60 constants.CONST.__getattribute__('dir_results'), 'robot')
61 self.xml_file = os.path.join(self.res_dir, 'output.xml')
62 super(RobotFramework, self).__init__(**kwargs)
64 def parse_results(self):
65 """Parse output.xml and get the details in it."""
66 result = robot.api.ExecutionResult(self.xml_file)
67 visitor = ResultVisitor()
71 result.suite.statistics.critical.passed /
72 result.suite.statistics.critical.total)
73 except ZeroDivisionError:
74 self.__logger.error("No test has been run")
75 self.start_time = timestamp_to_secs(result.suite.starttime)
76 self.stop_time = timestamp_to_secs(result.suite.endtime)
78 self.details['description'] = result.suite.name
79 self.details['tests'] = visitor.get_data()
81 def run(self, **kwargs):
82 """Run the RobotFramework suites
85 * create the output directories if required,
86 * get the results in output.xml,
87 * delete temporary files.
90 kwargs: Arbitrary keyword arguments.
93 EX_OK if all suites ran well.
94 EX_RUN_ERROR otherwise.
97 suites = kwargs["suites"]
98 variable = kwargs.get("variable", [])
100 self.__logger.exception("Mandatory args were not passed")
101 return self.EX_RUN_ERROR
103 os.makedirs(self.res_dir)
104 except OSError as ex:
105 if ex.errno != errno.EEXIST:
106 self.__logger.exception("Cannot create %s", self.res_dir)
107 return self.EX_RUN_ERROR
108 except Exception: # pylint: disable=broad-except
109 self.__logger.exception("Cannot create %s", self.res_dir)
110 return self.EX_RUN_ERROR
112 robot.run(*suites, variable=variable, output=self.xml_file,
113 log='NONE', report='NONE', stdout=stream)
114 self.__logger.info("\n" + stream.getvalue())
115 self.__logger.info("Results were successfully generated")
118 self.__logger.info("Results were successfully parsed")
119 except RobotError as ex:
120 self.__logger.error("Run suites before publishing: %s", ex.message)
121 return self.EX_RUN_ERROR
122 except Exception: # pylint: disable=broad-except
123 self.__logger.exception("Cannot parse results")
124 return self.EX_RUN_ERROR