1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#!/usr/bin/env python
# Copyright (c) 2017 Orange and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
"""Define classes required to run any Robot suites."""
from __future__ import division
import errno
import logging
import os
import robot.api
from robot.errors import RobotError
import robot.run
from robot.utils.robottime import timestamp_to_secs
from six import StringIO
from functest.core import testcase
from functest.utils import constants
__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
class ResultVisitor(robot.api.ResultVisitor):
"""Visitor to get result details."""
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['starttime'] = 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):
"""Get the details of the result."""
return self._data
class RobotFramework(testcase.TestCase):
"""RobotFramework runner."""
__logger = logging.getLogger(__name__)
def __init__(self, **kwargs):
self.res_dir = os.path.join(
constants.CONST.__getattribute__('dir_results'), 'robot')
self.xml_file = os.path.join(self.res_dir, 'output.xml')
super(RobotFramework, self).__init__(**kwargs)
def parse_results(self):
"""Parse output.xml and get the details in it."""
result = robot.api.ExecutionResult(self.xml_file)
visitor = ResultVisitor()
result.visit(visitor)
try:
self.result = 100 * (
result.suite.statistics.critical.passed /
result.suite.statistics.critical.total)
except ZeroDivisionError:
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 = {}
self.details['description'] = result.suite.name
self.details['tests'] = visitor.get_data()
def run(self, **kwargs):
"""Run the RobotFramework suites
Here are the steps:
* create the output directories if required,
* get the results in output.xml,
* delete temporary files.
Args:
kwargs: Arbitrary keyword arguments.
Returns:
EX_OK if all suites ran well.
EX_RUN_ERROR otherwise.
"""
try:
suites = kwargs["suites"]
variable = kwargs.get("variable", [])
except KeyError:
self.__logger.exception("Mandatory args were not passed")
return self.EX_RUN_ERROR
try:
os.makedirs(self.res_dir)
except OSError as ex:
if ex.errno != errno.EEXIST:
self.__logger.exception("Cannot create %s", self.res_dir)
return self.EX_RUN_ERROR
except Exception: # pylint: disable=broad-except
self.__logger.exception("Cannot create %s", self.res_dir)
return self.EX_RUN_ERROR
stream = StringIO()
robot.run(*suites, variable=variable, output=self.xml_file,
log='NONE', report='NONE', stdout=stream)
self.__logger.info("\n" + stream.getvalue())
self.__logger.info("Results were successfully generated")
try:
self.parse_results()
self.__logger.info("Results were successfully parsed")
except RobotError as ex:
self.__logger.error("Run suites before publishing: %s", ex.message)
return self.EX_RUN_ERROR
except Exception: # pylint: disable=broad-except
self.__logger.exception("Cannot parse results")
return self.EX_RUN_ERROR
return self.EX_OK
|