CSIT-395 Update TRex version to v2.09
[csit.git] / resources / tools / robot_output_parser_publish.py
1 #!/usr/bin/python
2
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:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
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.
15
16 """Script extracts intersted data (name, documentation, message, status) from
17 robot framework output file (output.xml) and print in specified format (wiki,
18 html) to stdout or, if specified by parameter, redirect to file."""
19
20 import argparse
21 import re
22 import sys
23
24 from robot.api import ExecutionResult, ResultVisitor
25
26
27 class ExecutionChecker(ResultVisitor):
28     """Abstract class to traverse through the test suite structure."""
29
30     def __init__(self, args):
31         self.formatting = args.formatting
32
33     def visit_suite(self, suite):
34         """Implements traversing through the suite and its direct children.
35
36         :param suite: Suite to process.
37         :type suite: Suite
38         :return: Nothing.
39         """
40
41         if self.start_suite(suite) is not False:
42             if suite.tests:
43                 if self.formatting == 'html':
44                     sys.stdout.write('<table width=100% border=1><tr>'+'\n')
45                     sys.stdout.write('<th width=32%>Name</th>'+'\n')
46                     sys.stdout.write('<th width=40%>Documentation</th>'+'\n')
47                     if "Perf" and "Long" in suite.longname:
48                         sys.stdout.write('<th width=24%>Message</th>'+'\n')
49                     sys.stdout.write('<th width=4%>Status</th><tr/>'+'\n')
50                     sys.stdout.write('</tr>')
51                 elif self.formatting == 'wiki':
52                     sys.stdout.write('{| class="wikitable"'+'\n')
53                     if "Perf" and "Long" in suite.longname:
54                         header = '!Name!!Documentation!!Message!!Status'
55                     else:
56                         header = '!Name!!Documentation!!Status'
57                     sys.stdout.write(header+'\n')
58                 else:
59                     pass
60
61             suite.suites.visit(self)
62             suite.tests.visit(self)
63
64             if suite.tests:
65                 if self.formatting == 'html':
66                     sys.stdout.write('</table>'+'\n')
67                 elif self.formatting == 'wiki':
68                     sys.stdout.write('|}'+'\n')
69                 else:
70                     pass
71
72             self.end_suite(suite)
73
74     def start_suite(self, suite):
75         """Called when suite starts.
76
77         :param suite: Suite to process.
78         :type suite: Suite
79         :return: Nothing.
80         """
81
82         level = len(suite.longname.split("."))
83
84         if self.formatting == 'html':
85             mark_l = '<h'+str(level)+'>'
86             mark_r = '</h'+str(level)+'>'
87             sys.stdout.write(mark_l+suite.name+mark_r+'\n')
88             sys.stdout.write('<p>'+re.sub(r"(\*)(.*?)(\*)", r"<b>\2</b>",\
89                 suite.doc, 0, flags=re.MULTILINE).replace(\
90                 '[', '<br>[')+'</p>\n')
91
92         elif self.formatting == 'wiki':
93             mark = "=" * (level+2)
94             sys.stdout.write(mark+suite.name+mark+'\n')
95             sys.stdout.write(re.sub(r"(\*)(.*?)(\*)", r"\n*'''\2'''",\
96                 suite.doc.replace('\n', ' '), 0, flags=re.MULTILINE)+'\n')
97         else:
98             pass
99
100     def end_suite(self, suite):
101         """Called when suite ends.
102
103         :param suite: Suite to process.
104         :type suite: Suite
105         :return: Nothing.
106         """
107
108         pass
109
110     def visit_test(self, test):
111         """Implements traversing through the test.
112
113         :param test: Test to process.
114         :type test: Test
115         :return: Nothing.
116         """
117
118         if self.start_test(test) is not False:
119             self.end_test(test)
120
121     def start_test(self, test):
122         """Called when test starts.
123
124         :param test: Test to process.
125         :type test: Test
126         :return: Nothing.
127         """
128
129         if self.formatting == 'html':
130             sys.stdout.write('<tr>'+'\n')
131             sys.stdout.write('<td>'+test.name+'</td>'+'\n')
132             sys.stdout.write('<td>'+test.doc+'</td>'+'\n')
133             if any("PERFTEST_LONG" in tag for tag in test.tags):
134                 sys.stdout.write('<td>'+test.message+'</td>'+'\n')
135             sys.stdout.write('<td>'+test.status+'</td>'+'\n')
136         elif self.formatting == 'wiki':
137             sys.stdout.write('|-'+'\n')
138             sys.stdout.write('|'+test.name+'\n')
139             sys.stdout.write('|'+test.doc.replace('\n', ' ').replace('\r',\
140                 '')+'\n')
141             if any("PERFTEST_LONG" in tag for tag in test.tags):
142                 sys.stdout.write('|'+test.message+'\n')
143             sys.stdout.write('|'+test.status+'\n')
144         else:
145             pass
146
147     def end_test(self, test):
148         """Called when test ends.
149
150         :param test: Test to process.
151         :type test: Test
152         :return: Nothing.
153         """
154
155         if self.formatting == 'html':
156             sys.stdout.write('</tr>'+'\n')
157         elif self.formatting == 'wiki':
158             pass
159         else:
160             pass
161
162
163 def process_robot_file(args):
164     """Process data from robot output.xml file and return raw data.
165
166     :param args: Parsed arguments.
167     :type args: ArgumentParser
168     :return: Nothing.
169     """
170
171     result = ExecutionResult(args.input)
172     checker = ExecutionChecker(args)
173     result.visit(checker)
174
175
176 def print_error(msg):
177     """Print error message on stderr.
178
179     :param msg: Error message to print.
180     :type msg: str
181     :return: nothing
182     """
183
184     sys.stderr.write(msg+'\n')
185
186
187 def parse_args():
188     """Parse arguments from cmd line.
189
190     :return: Parsed arguments.
191     :rtype ArgumentParser
192     """
193
194     parser = argparse.ArgumentParser()
195     parser.add_argument("-i", "--input", required=True,
196                         type=argparse.FileType('r'),
197                         help="Robot XML log file")
198     parser.add_argument("-o", "--output",
199                         type=argparse.FileType('w'),
200                         help="Output file")
201     parser.add_argument("-f", "--formatting", required=True,
202                         choices=['html', 'wiki'],
203                         help="Output file format")
204
205     return parser.parse_args()
206
207
208 def main():
209     """Main function."""
210
211     args = parse_args()
212
213     if args.output:
214         sys.stdout = args.output
215
216     process_robot_file(args)
217
218
219 if __name__ == "__main__":
220     sys.exit(main())