92038b59038d24e5f5cc072f7283b173b9e1594d
[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+'\n')
140             if any("PERFTEST_LONG" in tag for tag in test.tags):
141                 sys.stdout.write('|'+test.message+'\n')
142             sys.stdout.write('|'+test.status+'\n')
143         else:
144             pass
145
146     def end_test(self, test):
147         """Called when test ends.
148
149         :param test: Test to process.
150         :type test: Test
151         :return: Nothing.
152         """
153
154         if self.formatting == 'html':
155             sys.stdout.write('</tr>'+'\n')
156         elif self.formatting == 'wiki':
157             pass
158         else:
159             pass
160
161
162 def process_robot_file(args):
163     """Process data from robot output.xml file and return raw data.
164
165     :param args: Parsed arguments.
166     :type args: ArgumentParser
167     :return: Nothing.
168     """
169
170     result = ExecutionResult(args.input)
171     checker = ExecutionChecker(args)
172     result.visit(checker)
173
174
175 def print_error(msg):
176     """Print error message on stderr.
177
178     :param msg: Error message to print.
179     :type msg: str
180     :return: nothing
181     """
182
183     sys.stderr.write(msg+'\n')
184
185
186 def parse_args():
187     """Parse arguments from cmd line.
188
189     :return: Parsed arguments.
190     :rtype ArgumentParser
191     """
192
193     parser = argparse.ArgumentParser()
194     parser.add_argument("-i", "--input", required=True,
195                         type=argparse.FileType('r'),
196                         help="Robot XML log file")
197     parser.add_argument("-o", "--output",
198                         type=argparse.FileType('w'),
199                         help="Output file")
200     parser.add_argument("-f", "--formatting", required=True,
201                         choices=['html', 'wiki'],
202                         help="Output file format")
203
204     return parser.parse_args()
205
206
207 def main():
208     """Main function."""
209
210     args = parse_args()
211
212     if args.output:
213         sys.stdout = args.output
214
215     process_robot_file(args)
216
217
218 if __name__ == "__main__":
219     sys.exit(main())