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
|
"""
Classes for merging several reports into one
"""
from __future__ import unicode_literals
from typing import TYPE_CHECKING
import os
import xml.etree.ElementTree as ET
from io import BytesIO
from . import parser
from .render import ReportContainer
from .textutils import unicode_str
if TYPE_CHECKING: # pragma: no cover
from typing import List
def is_junit_file(filepath: str):
"""
Return True if this might be a junit xml file.
:return:
"""
try:
with open(filepath, "r", encoding="utf-8") as fh:
start = fh.read(512)
for fragment in ["<testsuite", "<testrun"]:
if fragment in start:
return True
except UnicodeDecodeError:
pass
return False
class Merger(ReportContainer, parser.ToJunitXmlBase):
"""
Utility class to create a merged junix xml report
"""
suites: "List[parser.Suite]"
def __init__(self):
super(Merger, self).__init__()
self.suites = []
def add_report(self, filename: str):
"""
Load a test report or folder
:param filename:
:return:
"""
if os.path.isfile(filename):
report = parser.Junit(filename)
self.reports[filename] = report
for suite in report.suites:
self.suites.append(suite)
elif os.path.isdir(filename):
# try importing all files in this folder
for root, dirs, files in os.walk(filename):
for filename in files:
filepath = os.path.join(root, filename)
try:
if is_junit_file(filepath):
try:
self.add_report(filepath)
except (parser.ParserError, ET.ParseError):
pass
except UnicodeDecodeError:
pass
def add_suite(self, suite: "parser.Suite"):
"""
Add a suite to the merge
:param suite:
:return:
"""
self.suites.append(suite)
def calculate_duration(self):
"""
Add up the time values in all testcases
:return:
"""
total = 0
for suite in self.suites:
for testcase in suite.all():
total += testcase.duration
return total
def tojunit(self):
"""
Render a merged xml report
:return:
"""
root = self.make_element("testsuites")
root.set(u"duration", unicode_str(self.calculate_duration()))
for suite in self.suites:
root.append(suite.tojunit())
return root
def toxmlstring(self):
"""
Render the xml document as a string
:return:
"""
tree = ET.ElementTree(self.tojunit())
buf = BytesIO()
tree.write(buf)
return u'<?xml version="1.0" encoding="utf-8"?>' + u"\n" + unicode_str(buf.getvalue())
|