3 # Copyright (c) 2016 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 """Script parses the data taken by robot framework (output.xml) and dumps
17 intereted values into XML output file."""
21 import xml.etree.ElementTree as ET
23 from robot.api import ExecutionResult, ResultVisitor
26 class ExecutionChecker(ResultVisitor):
27 """Iterates through test cases."""
29 def __init__(self, args):
30 self.root = ET.Element('build',
31 attrib={'vdevice': args.vdevice})
33 def visit_suite(self, suite):
34 """Implements traversing through the suite and its direct children.
36 :param suite: Suite to process.
40 if self.start_suite(suite) is not False:
41 suite.suites.visit(self)
42 suite.tests.visit(self)
45 def start_suite(self, suite):
46 """Called when suite starts.
48 :param suite: Suite to process.
54 def end_suite(self, suite):
55 """Called when suite ends.
57 :param suite: Suite to process.
63 def visit_test(self, test):
64 """Implements traversing through the test.
66 :param test: Test to process.
70 if self.start_test(test) is not False:
73 def start_test(self, test):
74 """Called when test starts.
76 :param test: Test to process.
80 if any("PERFTEST_LONG" in tag for tag in test.tags):
81 if test.status == 'PASS':
85 for keyword in test.keywords:
86 for assign in keyword.assign:
87 if assign == '${framesize}':
88 framesize = keyword.args[0]
89 if 'worker threads' in keyword.name:
90 workers = keyword.name.split('\'')[1]
91 workers_per_nic = keyword.name.split('\'')[3]
93 test_elem = ET.SubElement(self.root,
94 test.parent.name.replace(" ",""))
95 test_elem.attrib['name'] = test.parent.name
96 test_elem.attrib['workerthreads'] = workers
97 test_elem.attrib['workerspernic'] = workers_per_nic
98 test_elem.attrib['framesize'] = framesize
99 test_elem.attrib['tags'] = ', '.join(tags)
100 test_elem.text = test.message.split(' ')[1]
102 def end_test(self, test):
103 """Called when test ends.
105 :param test: Test to process.
112 def parse_tests(args):
113 """Process data from robot output.xml file and return XML data.
115 :param args: Parsed arguments.
116 :type args: ArgumentParser
118 :return: XML formatted output.
122 result = ExecutionResult(args.input)
123 checker = ExecutionChecker(args)
124 result.visit(checker)
129 def print_error(msg):
130 """Print error message on stderr.
132 :param msg: Error message to print.
137 sys.stderr.write(msg+'\n')
141 """Parse arguments from cmd line.
143 :return: Parsed arguments.
144 :rtype ArgumentParser
147 parser = argparse.ArgumentParser()
148 parser.add_argument("-i", "--input", required=True,
149 type=argparse.FileType('r'),
150 help="Robot XML log file")
151 parser.add_argument("-o", "--output", required=True,
152 type=argparse.FileType('w'),
153 help="XML output file")
154 parser.add_argument("-v", "--vdevice", required=True,
157 return parser.parse_args()
165 root = parse_tests(args)
166 ET.ElementTree.write(ET.ElementTree(root), args.output)
169 if __name__ == "__main__":