Skip to content

Commit c5c42c0

Browse files
committed
python-stdlib/unittest: Report (Un)Expected failures.
The could be submitted as a separate PR, but is included here to allow better reporting of the tests results of different typing variants. Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
1 parent 96fb839 commit c5c42c0

1 file changed

Lines changed: 58 additions & 9 deletions

File tree

python-stdlib/unittest/unittest/__init__.py

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,21 @@ def skipUnless(cond, msg):
228228
return skip(msg)
229229

230230

231+
class _ExpectedFailure(Exception):
232+
pass
233+
234+
235+
class _UnexpectedSuccess(Exception):
236+
pass
237+
238+
231239
def expectedFailure(test):
232240
def test_exp_fail(*args, **kwargs):
233241
try:
234242
test(*args, **kwargs)
235-
except:
236-
pass
237-
else:
238-
assert False, "unexpected success"
243+
except Exception:
244+
raise _ExpectedFailure
245+
raise _UnexpectedSuccess
239246

240247
return test_exp_fail
241248

@@ -270,12 +277,29 @@ def run(self, suite: TestSuite):
270277
res.printErrors()
271278
print("----------------------------------------------------------------------")
272279
print("Ran %d tests\n" % res.testsRun)
273-
if res.failuresNum > 0 or res.errorsNum > 0:
274-
print("FAILED (failures=%d, errors=%d)" % (res.failuresNum, res.errorsNum))
280+
extras = []
281+
if res.skippedNum > 0:
282+
extras.append("skipped=%d" % res.skippedNum)
283+
if res.expectedFailuresNum > 0:
284+
extras.append("expected failures=%d" % res.expectedFailuresNum)
285+
if res.unexpectedSuccessesNum > 0:
286+
extras.append("unexpected successes=%d" % res.unexpectedSuccessesNum)
287+
if (res.failuresNum + res.errorsNum + res.unexpectedSuccessesNum) > 0:
288+
parts = [
289+
"failures=%d" % res.failuresNum,
290+
"errors=%d" % res.errorsNum,
291+
]
292+
if res.unexpectedSuccessesNum > 0:
293+
parts.append("unexpected successes=%d" % res.unexpectedSuccessesNum)
294+
if res.expectedFailuresNum > 0:
295+
parts.append("expected failures=%d" % res.expectedFailuresNum)
296+
if res.skippedNum > 0:
297+
parts.append("skipped=%d" % res.skippedNum)
298+
print("FAILED (%s)" % ", ".join(parts))
275299
else:
276300
msg = "OK"
277-
if res.skippedNum > 0:
278-
msg += " (skipped=%d)" % res.skippedNum
301+
if extras:
302+
msg += " (%s)" % ", ".join(extras)
279303
print(msg)
280304

281305
return res
@@ -289,14 +313,22 @@ def __init__(self):
289313
self.errorsNum = 0
290314
self.failuresNum = 0
291315
self.skippedNum = 0
316+
self.expectedFailuresNum = 0
317+
self.unexpectedSuccessesNum = 0
292318
self.testsRun = 0
293319
self.errors = []
294320
self.failures = []
295321
self.skipped = []
322+
self.expectedFailures = []
323+
self.unexpectedSuccesses = []
296324
self._newFailures = 0
297325

298326
def wasSuccessful(self):
299-
return self.errorsNum == 0 and self.failuresNum == 0
327+
return (
328+
self.errorsNum == 0
329+
and self.failuresNum == 0
330+
and self.unexpectedSuccessesNum == 0
331+
)
300332

301333
def printErrors(self):
302334
if self.errors or self.failures:
@@ -325,10 +357,14 @@ def __add__(self, other):
325357
self.errorsNum += other.errorsNum
326358
self.failuresNum += other.failuresNum
327359
self.skippedNum += other.skippedNum
360+
self.expectedFailuresNum += other.expectedFailuresNum
361+
self.unexpectedSuccessesNum += other.unexpectedSuccessesNum
328362
self.testsRun += other.testsRun
329363
self.errors.extend(other.errors)
330364
self.failures.extend(other.failures)
331365
self.skipped.extend(other.skipped)
366+
self.expectedFailures.extend(other.expectedFailures)
367+
self.unexpectedSuccesses.extend(other.unexpectedSuccesses)
332368
return self
333369

334370

@@ -353,6 +389,19 @@ def _handle_test_exception(
353389
test_result.skipped.append((current_test, reason))
354390
print(" skipped:", reason)
355391
return
392+
elif isinstance(exc, _ExpectedFailure):
393+
test_result.expectedFailuresNum += 1
394+
test_result.expectedFailures.append((current_test, ""))
395+
if verbose:
396+
print(" expected failure")
397+
return
398+
elif isinstance(exc, _UnexpectedSuccess):
399+
test_result.unexpectedSuccessesNum += 1
400+
test_result.unexpectedSuccesses.append((current_test, ""))
401+
if verbose:
402+
print(" unexpected success")
403+
test_result._newFailures += 1
404+
return
356405
elif isinstance(exc, AssertionError):
357406
test_result.failuresNum += 1
358407
test_result.failures.append((current_test, ex_str))

0 commit comments

Comments
 (0)