blob: 483a2c5aeab0a153d3f5d038cb95e378f9399df3 [file] [log] [blame]
George Keishing9fbdf792016-10-18 06:16:09 -05001#!/usr/bin/python
2r"""
3#############################################################
4# @brief Uses robot framework API to extract test result
5# data from output.xml generated by robot tests.
6# For more information on the Robot Framework API
7# http://robot-framework.readthedocs.io/en/3.0
8# /autodoc/robot.result.html
9#############################################################
10"""
11import sys
12import getopt
13import csv
14from datetime import datetime
15import robot.errors
16from robot.api import ExecutionResult
17from robot.result.visitor import ResultVisitor
George Keishing74777bd2017-02-07 01:43:38 -060018from xml.etree import ElementTree
19import re
George Keishing9fbdf792016-10-18 06:16:09 -050020
21
George Keishing74777bd2017-02-07 01:43:38 -060022def parse_output_xml(xml_file_path, csv_dir_path):
23 result = ExecutionResult(xml_file_path)
George Keishing9fbdf792016-10-18 06:16:09 -050024 result.configure(stat_config={'suite_stat_level': 2,
25 'tag_stat_combine': 'tagANDanother'})
26
27 stats = result.statistics
28 print "--------------------------------------"
29 print "Total Test Count:\t",\
30 stats.total.critical.passed + stats.total.critical.failed
31 print "Total Test Failed:\t", stats.total.critical.failed
32 print "Total Test Passed:\t", stats.total.critical.passed
33 print "Test Start Time:\t", result.suite.starttime
34 print "Test End Time:\t\t", result.suite.endtime
35 print "--------------------------------------"
36
37 # Use ResultVisitor object and save off the test data info
38 class TestResult(ResultVisitor):
39 def __init__(self):
40 self.testData = []
41
42 def visit_test(self, test):
43 self.testData += [test]
44
45 collectDataObj = TestResult()
46 result.visit(collectDataObj)
47
48 # Write the result statistics attributes to CSV file
49 l_csvlist = []
George Keishing74777bd2017-02-07 01:43:38 -060050
51 # Default Test data
George Keishing9fbdf792016-10-18 06:16:09 -050052 l_subsys = 'OPENBMC'
53 l_test_type = 'FTC'
54 l_pse_rel = 'OBMC910'
George Keishing74777bd2017-02-07 01:43:38 -060055 l_env = 'HW'
56 l_proc = 'P9'
57 l_platform_type = ""
58 l_func_area = ""
59
60 # System data from XML meta data
61 l_system_info = get_system_details(xml_file_path)
62 l_driver = l_system_info[0]
63 if l_system_info[1]:
64 l_platform_type = l_system_info[1]
65 else:
66 print "System model is not set"
67 sys.exit()
George Keishing9fbdf792016-10-18 06:16:09 -050068
69 # Default header
70 l_header = ['test_start', 'test_end', 'subsys', 'test_type',
George Keishing74777bd2017-02-07 01:43:38 -060071 'test_result', 'test_name', 'pse_rel', 'driver',
72 'env', 'proc', 'platform_type', 'test_func_area']
George Keishing9fbdf792016-10-18 06:16:09 -050073
74 l_csvlist.append(l_header)
75
76 # Generate CSV file onto the path with current time stamp
George Keishing74777bd2017-02-07 01:43:38 -060077 l_base_dir = csv_dir_path
George Keishing9fbdf792016-10-18 06:16:09 -050078 l_timestamp = datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S")
George Keishing74777bd2017-02-07 01:43:38 -060079 # Example: 2017-02-20-08-47-22_Witherspoon.csv
80 l_csvfile = l_base_dir + l_timestamp + "_" + l_platform_type + ".csv"
George Keishing9fbdf792016-10-18 06:16:09 -050081
82 print "Writing data into csv file:", l_csvfile
83
84 for testcase in collectDataObj.testData:
George Keishing74777bd2017-02-07 01:43:38 -060085 # Functional Area: Suite Name
86 # Test Name: Test Case Name
87 l_func_area = str(testcase.parent).split(' ', 1)[1]
88 l_test_name = str(testcase)
George Keishing9fbdf792016-10-18 06:16:09 -050089
90 # Test Result pass=0 fail=1
91 if testcase.status == 'PASS':
92 l_test_result = 0
93 else:
94 l_test_result = 1
95
George Keishing74777bd2017-02-07 01:43:38 -060096 # Format datetime from robot output.xml to "%Y-%m-%d-%H-%M-%S"
97 l_stime = xml_to_csv_time(testcase.starttime)
98 l_etime = xml_to_csv_time(testcase.endtime)
George Keishing9fbdf792016-10-18 06:16:09 -050099 # Data Sequence: test_start,test_end,subsys,test_type,
George Keishing74777bd2017-02-07 01:43:38 -0600100 # test_result,test_name,pse_rel,driver,
101 # env,proc,platform_tyep,test_func_area,
102 l_data = [l_stime, l_etime, l_subsys, l_test_type, l_test_result,
103 l_test_name, l_pse_rel, l_driver, l_env, l_proc,
104 l_platform_type, l_func_area]
George Keishing9fbdf792016-10-18 06:16:09 -0500105 l_csvlist.append(l_data)
106
George Keishinga96e27c2016-12-04 23:05:04 -0600107 # Open the file and write to the CSV file
108 l_file = open(l_csvfile, "w")
109 l_writer = csv.writer(l_file, lineterminator='\n')
110 l_writer.writerows(l_csvlist)
111 l_file.close()
George Keishing9fbdf792016-10-18 06:16:09 -0500112
113
George Keishing74777bd2017-02-07 01:43:38 -0600114def xml_to_csv_time(xml_datetime):
115 r"""
116 Convert the time from %Y%m%d %H:%M:%S.%f format to %Y-%m-%d-%H-%M-%S format
117 and return it.
118
119 Description of arguments:
120 datetime The date in the following format: %Y%m%d %H:%M:%S.%f
121 (This is the format typically found in an XML file.)
122
123 The date returned will be in the following format: %Y-%m-%d-%H-%M-%S
124 """
125 # 20170206 05:05:19.342
126 l_str = datetime.strptime(xml_datetime, "%Y%m%d %H:%M:%S.%f")
127 # 2017-02-06-05-05-19
128 l_str = l_str.strftime("%Y-%m-%d-%H-%M-%S")
129 return str(l_str)
130
131
132def get_system_details(xml_file_path):
133 r"""
134 Get the system data from output.xml generated by robot and return it.
Gunnar Mills28e403b2017-10-25 16:16:38 -0500135 The list returned will be in the following order: [driver,platform]
George Keishing74777bd2017-02-07 01:43:38 -0600136
137 Description of arguments:
138 xml_file_path The relative or absolute path to the output.xml file.
139 """
140 bmc_version = ""
141 bmc_platform = ""
142 with open(xml_file_path, 'rt') as output:
143 tree = ElementTree.parse(output)
144
145 for node in tree.iter('msg'):
146 # /etc/os-release output is logged in the XML as msg
147 # Example: ${output} = VERSION_ID="v1.99.2-71-gbc49f79-dirty"
148 if '${output} = VERSION_ID=' in node.text:
149 # Get BMC version (e.g. v1.99.1-96-g2a46570-dirty)
150 bmc_version = str(node.text.split("VERSION_ID=")[1])[1:-1]
151
152 # Platform is logged in the XML as msg.
153 # Example: ${bmc_model} = Witherspoon BMC
154 if '${bmc_model} = ' in node.text:
155 bmc_platform = node.text.split(" = ")[1]
156
157 print "BMC Version:", bmc_version
158 print "BMC Platform:", bmc_platform
George Keishing3f2d1922017-03-07 00:30:44 -0600159 return [str(bmc_version), str(bmc_platform)]
George Keishing74777bd2017-02-07 01:43:38 -0600160
161
George Keishing9fbdf792016-10-18 06:16:09 -0500162def usage():
163 name = 'gen_csv_results.py'
164 print 'Usage: '
165 print name, '-s <source path> -d <destination path>'
166 print '\t-s | --source= : output.xml robot test result file path'
167 print '\t-d | --dest= : Where the *.csv file will be generated'
168 sys.exit()
169
170
171def main(argv):
172
173 source = ''
174 dest = ''
175 try:
176 opts, args = getopt.getopt(argv, "h:s:d:", ["source=", "dest="])
177 except getopt.GetoptError:
178 usage()
179
180 for opt, arg in opts:
181 if opt == '-h':
182 usage()
183 elif opt in ("-s", "--source"):
184 source = arg
185 elif opt in ("-d", "--dest"):
186 dest = arg
187
188 if source == '':
189 usage()
190 print 'ERROR: Provide input file path to robot generated output.xml '
191
192 if dest == '':
193 usage()
194 print 'ERROR: Destination directory where *.csv file will be generated'
195
196 parse_output_xml(source, dest)
197
198if __name__ == "__main__":
199 main(sys.argv[1:])