1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
#!/usr/bin/env python
'''
This script generates jUnit-style xml files from the log written by our tests.
This xml file is used in Jenkins to show the state of the test execution.
Created on May 13, 2015
@author: t.danshin
'''
from __future__ import print_function
import getopt
import sys
import xml.etree.ElementTree as ElementTree
class TestInfo:
def __init__(self, test_name):
self.test_suite, name = test_name.split("::", 1)
self.test_suite = self.test_suite[0: -4]
name = name.replace("::", ".")
self.test_name = name
self.test_comment = None
self.test_result = None
self.test_duration = 0.0
def append_comment(self, comment):
if self.test_comment is None:
self.test_comment = comment
else:
self.test_comment += "\n" + comment
def __repr__(self):
local_comment = ""
if self.test_comment is not None:
local_comment = self.test_comment
return "{}::{}: {} -> {}\n".format(self.test_suite, self.test_name, local_comment, self.test_result)
def xml(self):
d = ElementTree.Element("testcase", {"name":self.test_name, "classname":self.test_suite, "time":str(self.test_duration)})
if self.test_comment is not None:
b = ElementTree.SubElement(d, "system-err")
b.text = self.test_comment
if self.test_result == "FAILED":
ElementTree.SubElement(d, "failure")
return d
def set_duration(self, milis):
self.test_duration = float(milis)
class Parser:
def __init__(self, logfile, xml_file):
self.logfile = logfile if logfile else "testlog.log"
self.xml_file = xml_file if xml_file else "test_results.xml"
self.root = ElementTree.Element("testsuite")
def parse_log_file(self):
with open(self.logfile) as f:
test_info = None
for line in f.readlines():
line = line.rstrip().decode('utf-8')
if line.startswith("Running"):
test_info = TestInfo(line[len("Running "):])
elif line.startswith("Test took"):
if test_info is not None:
test_info.set_duration(line[len("Test took "):-3])
self.root.append(test_info.xml())
test_info = None
elif line == "OK" or line.startswith("FAILED"):
if test_info is not None:
test_info.test_result = line
else:
if test_info is not None:
test_info.append_comment(line)
def write_xml_file(self):
print(">>> Self xml file: {}".format(self.xml_file))
ElementTree.ElementTree(self.root).write(self.xml_file, encoding="UTF-8", xml_declaration=True)
def usage():
print("""
Possbile options:
-h --help : print this help
-i --input : the path of the original log file to parse
-o --output: the path of the output xml file
Example
./testlog_to_xml_converter.py -i testlog.log -o /Users/t.danshin/Desktop/testxml.xml
""")
def read_cl_options():
try:
opts, args = getopt.getopt(sys.argv[1:], "hi:o:",
["help", "input=", "output="])
except getopt.GetoptError as err:
print(str(err))
usage()
sys.exit(2)
ret = {}
for option, argument in opts:
if option in ("-h", "--help"):
usage()
sys.exit()
elif option in ("-i", "--input"):
ret["logfile"] = argument
elif option in ("-o", "--output"):
ret["xml_file"] = argument
else:
assert False, "unhandled option"
return ret
def main():
options = read_cl_options()
try:
parser = Parser(options["logfile"], options["xml_file"])
except:
usage()
exit(2)
parser.parse_log_file()
parser.write_xml_file()
print("Finished writing the xUnit-style xml file")
if __name__ == '__main__':
main()
|