3 import xml
.etree
.ElementTree
as ET
10 print("Usage: xunit-summary.py <path to xunit results (*.xml)>")
12 test_dir
= sys
.argv
[1]
14 class AssemblyTestResults():
15 def __init__(self
, name
, total
, passed
, failed
, skipped
, errors
, time
):
19 self
.failed
= failed
+ errors
20 self
.skipped
= skipped
24 def __init__(self
, name
, time
):
31 for testfile
in glob
.glob(test_dir
+ "/*-xunit.xml"):
32 assemblies
= ET
.parse(testfile
).getroot()
33 for assembly
in assemblies
:
34 test_name
= assembly
.attrib
.get("name")
36 print("WARNING: %s has no tests!" % ntpath
.basename(testfile
))
38 test_assemblies
.append(AssemblyTestResults(test_name
,
39 int(assembly
.attrib
["total"]),
40 int(assembly
.attrib
["passed"]),
41 int(assembly
.attrib
["failed"]),
42 int(assembly
.attrib
["skipped"]),
43 int(assembly
.attrib
["errors"]),
44 float(assembly
.attrib
["time"])))
45 for collection
in assembly
.iter("collection"):
46 for test
in collection
.iter("test"):
47 test_items
.append(TestInfo(test
.attrib
["name"],
48 float(test
.attrib
["time"])))
50 test_assemblies
.sort(key
=lambda item
: (item
.failed
, item
.name
), reverse
=True)
51 test_items
.sort(key
=lambda item
: (item
.time
), reverse
=True)
56 for t
in test_assemblies
:
57 #if t.failed > 0: # uncomment to list only test suits with failures
58 print("{0:<60} Total:{1:<6} Failed:{2:<6} Time:{3} sec".format(t
.name
, t
.total
, t
.failed
, round(t
.time
, 1)))
61 print("Total test suites: %d" % len(test_assemblies
))
62 print("Total tests run: %d" % sum(x
.total
for x
in test_assemblies
))
63 print("Total tests passed: %d" % sum(x
.passed
for x
in test_assemblies
))
64 print("Total tests failed: %d" % sum(x
.failed
for x
in test_assemblies
))
65 print("Total tests skipped: %d" % sum(x
.skipped
for x
in test_assemblies
))
66 print("Total duration: %d min" % (sum(x
.time
for x
in test_assemblies
) / 60))
69 print("Top 20 slowest tests:")
71 for t
in test_items
[:20]:
72 print("{0:<89} Time:{1} sec".format(t
.name
[:88], round(t
.time
, 1)))