3 # Pretty-format subunit output
4 # Copyright (C) 2008-2010 Jelmer Vernooij <jelmer@samba.org>
5 # Published under the GNU GPL, v3 or later
12 sys
.path
.insert(0, os
.path
.join(os
.path
.dirname(__file__
), "../lib/subunit/python"))
13 sys
.path
.insert(0, os
.path
.join(os
.path
.dirname(__file__
), "../lib/testtools"))
18 class PlainFormatter(object):
20 def __init__(self
, summaryfile
, verbose
, immediate
, statistics
,
22 self
.verbose
= verbose
23 self
.immediate
= immediate
24 self
.statistics
= statistics
25 self
.start_time
= None
27 self
.suitesfailed
= []
30 self
.summaryfile
= summaryfile
33 self
._progress
_level
= 0
34 self
.totalsuites
= totaltests
36 def progress(self
, offset
, whence
):
37 if whence
== subunit
.PROGRESS_POP
:
38 self
._progress
_level
-= 1
39 elif whence
== subunit
.PROGRESS_PUSH
:
40 self
._progress
_level
+= 1
41 elif whence
== subunit
.PROGRESS_SET
:
42 if self
._progress
_level
== 0:
43 self
.totalsuites
= offset
44 elif whence
== subunit
.PROGRESS_CUR
:
45 raise NotImplementedError
47 def report_time(self
, time
):
48 if self
.start_time
is None:
49 self
.start_time
= time
52 def start_testsuite(self
, name
):
55 testsuite_start_time
= self
.last_time
57 duration
= testsuite_start_time
- self
.start_time
60 self
.test_output
[name
] = ""
62 out
= "[%d" % self
.index
63 if self
.totalsuites
is not None:
64 out
+= "/%d" % self
.totalsuites
65 out
+= " in %ds" % duration
67 out
+= ", %d errors" % (len(self
.suitesfailed
),)
70 sys
.stdout
.write(out
+ "\n")
72 sys
.stdout
.write(out
+ ": ")
74 def output_msg(self
, output
):
76 sys
.stdout
.write(output
)
77 elif self
.name
is not None:
78 self
.test_output
[self
.name
] += output
80 sys
.stdout
.write(output
)
82 def control_msg(self
, output
):
83 #$self->output_msg($output)
86 def end_testsuite(self
, name
, result
, reason
):
90 if not name
in self
.test_output
:
91 print "no output for name[%s]" % name
93 if result
in ("success", "xfail"):
96 self
.output_msg("ERROR: Testsuite[%s]\n" % name
)
97 if reason
is not None:
98 self
.output_msg("REASON: %s\n" % (reason
,))
99 self
.suitesfailed
.append(name
)
100 if self
.immediate
and not self
.verbose
:
101 out
+= self
.test_output
[name
]
104 if not self
.immediate
:
108 out
+= " " + result
.upper() + "\n"
110 sys
.stdout
.write(out
)
112 def start_test(self
, testname
):
115 def end_test(self
, testname
, result
, unexpected
, reason
=None):
117 self
.test_output
[self
.name
] = ""
118 if not self
.immediate
:
123 'success': '.'}.get(result
, "?(%s)" % result
))
126 self
.test_output
[self
.name
] += "UNEXPECTED(%s): %s\n" % (result
, testname
)
127 if reason
is not None:
128 self
.test_output
[self
.name
] += "REASON: %s\n" % (reason
.strip(),)
130 if self
.immediate
and not self
.verbose
:
131 print self
.test_output
[self
.name
]
132 self
.test_output
[self
.name
] = ""
134 if not self
.immediate
:
138 'success': 'S'}.get(result
, "?"))
141 f
= open(self
.summaryfile
, 'w+')
143 if self
.suitesfailed
:
144 f
.write("= Failed tests =\n")
146 for suite
in self
.suitesfailed
:
147 f
.write("== %s ==\n" % suite
)
148 f
.write(self
.test_output
[suite
]+"\n\n")
152 if not self
.immediate
and not self
.verbose
:
153 for suite
in self
.suitesfailed
:
155 print "FAIL: %s" % suite
156 print self
.test_output
[suite
]
159 f
.write("= Skipped tests =\n")
160 for reason
in self
.skips
.keys():
161 f
.write(reason
+ "\n")
162 for name
in self
.skips
[reason
]:
163 f
.write("\t%s\n" % name
)
167 print "\nA summary with detailed information can be found in:"
168 print " %s" % self
.summaryfile
170 if not self
.suitesfailed
:
171 ok
= (self
.statistics
['TESTS_EXPECTED_OK'] +
172 self
.statistics
['TESTS_EXPECTED_FAIL'])
173 print "\nALL OK (%d tests in %d testsuites)" % (ok
, self
.suites_ok
)
175 print "\nFAILED (%d failures and %d errors in %d testsuites)" % (
176 self
.statistics
['TESTS_UNEXPECTED_FAIL'],
177 self
.statistics
['TESTS_ERROR'],
178 len(self
.suitesfailed
))
180 def skip_testsuite(self
, name
, reason
="UNKNOWN"):
181 self
.skips
.setdefault(reason
, []).append(name
)
185 parser
= optparse
.OptionParser("format-subunit [options]")
186 parser
.add_option("--verbose", action
="store_true",
188 parser
.add_option("--immediate", action
="store_true",
189 help="Show failures immediately, don't wait until test run has finished")
190 parser
.add_option("--prefix", type="string", default
=".",
191 help="Prefix to write summary to")
193 opts
, args
= parser
.parse_args()
197 'TESTS_UNEXPECTED_OK': 0,
198 'TESTS_EXPECTED_OK': 0,
199 'TESTS_UNEXPECTED_FAIL': 0,
200 'TESTS_EXPECTED_FAIL': 0,
205 def handle_sigint(sig
, stack
):
207 signal
.signal(signal
.SIGINT
, handle_sigint
)
209 msg_ops
= PlainFormatter(os
.path
.join(opts
.prefix
, "summary"), opts
.verbose
,
210 opts
.immediate
, statistics
)
212 expected_ret
= subunithelper
.parse_results(msg_ops
, statistics
, sys
.stdin
)
216 sys
.exit(expected_ret
)