blob: 483a2c5aeab0a153d3f5d038cb95e378f9399df3 [file] [log] [blame]
#!/usr/bin/python
r"""
#############################################################
# @brief Uses robot framework API to extract test result
# data from output.xml generated by robot tests.
# For more information on the Robot Framework API
# http://robot-framework.readthedocs.io/en/3.0
# /autodoc/robot.result.html
#############################################################
"""
import sys
import getopt
import csv
from datetime import datetime
import robot.errors
from robot.api import ExecutionResult
from robot.result.visitor import ResultVisitor
from xml.etree import ElementTree
import re
def parse_output_xml(xml_file_path, csv_dir_path):
result = ExecutionResult(xml_file_path)
result.configure(stat_config={'suite_stat_level': 2,
'tag_stat_combine': 'tagANDanother'})
stats = result.statistics
print "--------------------------------------"
print "Total Test Count:\t",\
stats.total.critical.passed + stats.total.critical.failed
print "Total Test Failed:\t", stats.total.critical.failed
print "Total Test Passed:\t", stats.total.critical.passed
print "Test Start Time:\t", result.suite.starttime
print "Test End Time:\t\t", result.suite.endtime
print "--------------------------------------"
# Use ResultVisitor object and save off the test data info
class TestResult(ResultVisitor):
def __init__(self):
self.testData = []
def visit_test(self, test):
self.testData += [test]
collectDataObj = TestResult()
result.visit(collectDataObj)
# Write the result statistics attributes to CSV file
l_csvlist = []
# Default Test data
l_subsys = 'OPENBMC'
l_test_type = 'FTC'
l_pse_rel = 'OBMC910'
l_env = 'HW'
l_proc = 'P9'
l_platform_type = ""
l_func_area = ""
# System data from XML meta data
l_system_info = get_system_details(xml_file_path)
l_driver = l_system_info[0]
if l_system_info[1]:
l_platform_type = l_system_info[1]
else:
print "System model is not set"
sys.exit()
# Default header
l_header = ['test_start', 'test_end', 'subsys', 'test_type',
'test_result', 'test_name', 'pse_rel', 'driver',
'env', 'proc', 'platform_type', 'test_func_area']
l_csvlist.append(l_header)
# Generate CSV file onto the path with current time stamp
l_base_dir = csv_dir_path
l_timestamp = datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S")
# Example: 2017-02-20-08-47-22_Witherspoon.csv
l_csvfile = l_base_dir + l_timestamp + "_" + l_platform_type + ".csv"
print "Writing data into csv file:", l_csvfile
for testcase in collectDataObj.testData:
# Functional Area: Suite Name
# Test Name: Test Case Name
l_func_area = str(testcase.parent).split(' ', 1)[1]
l_test_name = str(testcase)
# Test Result pass=0 fail=1
if testcase.status == 'PASS':
l_test_result = 0
else:
l_test_result = 1
# Format datetime from robot output.xml to "%Y-%m-%d-%H-%M-%S"
l_stime = xml_to_csv_time(testcase.starttime)
l_etime = xml_to_csv_time(testcase.endtime)
# Data Sequence: test_start,test_end,subsys,test_type,
# test_result,test_name,pse_rel,driver,
# env,proc,platform_tyep,test_func_area,
l_data = [l_stime, l_etime, l_subsys, l_test_type, l_test_result,
l_test_name, l_pse_rel, l_driver, l_env, l_proc,
l_platform_type, l_func_area]
l_csvlist.append(l_data)
# Open the file and write to the CSV file
l_file = open(l_csvfile, "w")
l_writer = csv.writer(l_file, lineterminator='\n')
l_writer.writerows(l_csvlist)
l_file.close()
def xml_to_csv_time(xml_datetime):
r"""
Convert the time from %Y%m%d %H:%M:%S.%f format to %Y-%m-%d-%H-%M-%S format
and return it.
Description of arguments:
datetime The date in the following format: %Y%m%d %H:%M:%S.%f
(This is the format typically found in an XML file.)
The date returned will be in the following format: %Y-%m-%d-%H-%M-%S
"""
# 20170206 05:05:19.342
l_str = datetime.strptime(xml_datetime, "%Y%m%d %H:%M:%S.%f")
# 2017-02-06-05-05-19
l_str = l_str.strftime("%Y-%m-%d-%H-%M-%S")
return str(l_str)
def get_system_details(xml_file_path):
r"""
Get the system data from output.xml generated by robot and return it.
The list returned will be in the following order: [driver,platform]
Description of arguments:
xml_file_path The relative or absolute path to the output.xml file.
"""
bmc_version = ""
bmc_platform = ""
with open(xml_file_path, 'rt') as output:
tree = ElementTree.parse(output)
for node in tree.iter('msg'):
# /etc/os-release output is logged in the XML as msg
# Example: ${output} = VERSION_ID="v1.99.2-71-gbc49f79-dirty"
if '${output} = VERSION_ID=' in node.text:
# Get BMC version (e.g. v1.99.1-96-g2a46570-dirty)
bmc_version = str(node.text.split("VERSION_ID=")[1])[1:-1]
# Platform is logged in the XML as msg.
# Example: ${bmc_model} = Witherspoon BMC
if '${bmc_model} = ' in node.text:
bmc_platform = node.text.split(" = ")[1]
print "BMC Version:", bmc_version
print "BMC Platform:", bmc_platform
return [str(bmc_version), str(bmc_platform)]
def usage():
name = 'gen_csv_results.py'
print 'Usage: '
print name, '-s <source path> -d <destination path>'
print '\t-s | --source= : output.xml robot test result file path'
print '\t-d | --dest= : Where the *.csv file will be generated'
sys.exit()
def main(argv):
source = ''
dest = ''
try:
opts, args = getopt.getopt(argv, "h:s:d:", ["source=", "dest="])
except getopt.GetoptError:
usage()
for opt, arg in opts:
if opt == '-h':
usage()
elif opt in ("-s", "--source"):
source = arg
elif opt in ("-d", "--dest"):
dest = arg
if source == '':
usage()
print 'ERROR: Provide input file path to robot generated output.xml '
if dest == '':
usage()
print 'ERROR: Destination directory where *.csv file will be generated'
parse_output_xml(source, dest)
if __name__ == "__main__":
main(sys.argv[1:])