1 # Authors: Sylvain MARIE <sylvain.marie@se.com>
2 # + All contributors to <https://github.com/smarie/python-genbadge>
3 #
4 # License: 3-clause BSD, <https://github.com/smarie/python-genbadge/blob/master/LICENSE>
5 from __future__ import division
6
7 from io import TextIOWrapper
8
9 try:
10 from typing import Union
11 except ImportError:
12 pass
13
14 # use our own copy so as to use defusedxml and to be compliant with setuptools>=58
15 from .xunitparser_copy import parse
16 from .utils_badge import Badge
17
18
19 class TestStats(object):
20 """
21 Contains the results from parsing the Junit style test report (junit.xml).
22 Some stats are available as properties, computed based on others.
23 """
24 def __init__(self, runned, skipped, failed, errors):
25 self.runned = runned
26 self.failed = failed
27 self.skipped = skipped
28 self.errors = errors
29
30 @property
31 def success(self):
32 return self.runned - self.skipped - self.failed
33
34 @property
35 def total_with_skipped(self):
36 return self.runned + self.errors
37
38 @property
39 def total_without_skipped(self):
40 return self.runned - self.skipped + self.errors
41
42 @property
43 def success_percentage(self):
44 if self.runned > 0:
45 return self.success * 100 / self.total_without_skipped
46 else:
47 return 100
48
49 def __repr__(self):
50 return "%s(%s)" % (self.__class__.__name__, ",".join("%s=%r" % (k, v) for k, v in vars(self).items()))
51
52
53 def get_test_stats(junit_xml_file='reports/junit/junit.xml' # type: Union[str, TextIOWrapper]
54 ):
55 # type: (...) -> TestStats
56 """
57 read the junit test file and extract the success percentage
58 :param junit_xml_file: the junit xml file path or file/text stream
59 :return: the success percentage (an int)
60 """
61 if isinstance(junit_xml_file, str):
62 # assume a file path
63 with open(junit_xml_file) as f:
64 ts, tr = parse(f)
65 else:
66 # assume a stream already
67 ts, tr = parse(junit_xml_file)
68
69 runned = tr.testsRun
70 skipped = len(tr.skipped)
71 failed = len(tr.failures)
72 errors = len(tr.errors)
73
74 return TestStats(runned=runned, skipped=skipped, failed=failed, errors=errors)
75
76
77 def get_color(
78 test_stats # type: TestStats
79 ):
80 """ Returns the badge color to use depending on the success percentage """
81
82 if test_stats.success_percentage < 50:
83 color = 'red'
84 elif test_stats.success_percentage < 75:
85 color = 'orange'
86 elif test_stats.success_percentage < 90:
87 color = 'green'
88 else:
89 color = 'brightgreen'
90
91 return color
92
93
94 def get_tests_badge(
95 test_stats, # type: TestStats
-
E251
Unexpected spaces around keyword / parameter equals (in 2 places)
-
E261
At least two spaces before inline comment
96 left_txt = "tests" # type: str
97 ):
98 # type: (...) -> Badge
99 """Return the badge from test statistics """
100
101 color = get_color(test_stats)
102
103 if test_stats.success_percentage < 100:
104 # full badge
105 right_txt = "%s/%s" % (test_stats.success, test_stats.total_without_skipped)
106 else:
107 # simplified badge showing the number of tests
108 right_txt = "%s" % (test_stats.total_without_skipped,)
109
110 return Badge(left_txt=left_txt, right_txt=right_txt, color=color)