Skip to content

Commit

Permalink
unittest: Log failure tracebacks at test end.
Browse files Browse the repository at this point in the history
Store traceback details for each test failure and log to console at the end of the test.
  • Loading branch information
andrewleech committed Oct 31, 2018
1 parent 6ba4564 commit bf2a008
Showing 1 changed file with 28 additions and 6 deletions.
34 changes: 28 additions & 6 deletions unittest/unittest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import sys

try:
import io
except ImportError:
import uio as io

class SkipTest(Exception):
pass
Expand Down Expand Up @@ -157,7 +160,7 @@ class TestRunner:
def run(self, suite):
res = TestResult()
for c in suite.tests:
run_class(c, res)
res.exceptions.extend(run_class(c, res))

print("Ran %d tests\n" % res.testsRun)
if res.failuresNum > 0 or res.errorsNum > 0:
Expand All @@ -176,15 +179,30 @@ def __init__(self):
self.failuresNum = 0
self.skippedNum = 0
self.testsRun = 0
self.exceptions = []

def wasSuccessful(self):
return self.errorsNum == 0 and self.failuresNum == 0

if hasattr(sys, 'print_exception'):
print_exception = sys.print_exception
else:
import traceback
print_exception = lambda e, f: traceback.print_exception(None, e, sys.exc_info()[2], file=f)


def capture_exc(e):
buf = io.StringIO()
print_exception(e, buf)
return buf.getvalue()


# TODO: Uncompliant
def run_class(c, test_result):
o = c()
set_up = getattr(o, "setUp", lambda: None)
tear_down = getattr(o, "tearDown", lambda: None)
exceptions = []
for name in dir(o):
if name.startswith("test"):
print("%s (%s) ..." % (name, c.__qualname__), end="")
Expand All @@ -197,14 +215,14 @@ def run_class(c, test_result):
except SkipTest as e:
print(" skipped:", e.args[0])
test_result.skippedNum += 1
except:
except Exception as ex:
exceptions.append(capture_exc(ex))
print(" FAIL")
test_result.failuresNum += 1
# Uncomment to investigate failure in detail
#raise
continue
finally:
tear_down()
return exceptions


def main(module="__main__"):
Expand All @@ -214,11 +232,15 @@ def test_cases(m):
if isinstance(c, object) and isinstance(c, type) and issubclass(c, TestCase):
yield c

m = __import__(module)
m = __import__(module) if isinstance(module, str) else module
suite = TestSuite()
for c in test_cases(m):
suite.addTest(c)
runner = TestRunner()
result = runner.run(suite)
if result.exceptions:
sep = '\n----------------------------------------------------------------------\n'
print(sep)
print(sep.join(result.exceptions))
# Terminate with non zero return code in case of failures
sys.exit(result.failuresNum > 0)

0 comments on commit bf2a008

Please sign in to comment.