refine unittest support to also work with twisted trial test cases better by
introducing a slightly hackish way to report a failure upstream
This commit is contained in:
parent
6e6b0ab5d9
commit
695bffc83d
|
@ -329,6 +329,9 @@ class FunctionMixin(PyobjMixin):
|
|||
|
||||
def repr_failure(self, excinfo, outerr=None):
|
||||
assert outerr is None, "XXX outerr usage is deprecated"
|
||||
if excinfo.errisinstance(pytest.fail.Exception):
|
||||
if not excinfo.value.pytrace:
|
||||
return str(excinfo.value)
|
||||
return self._repr_failure_py(excinfo,
|
||||
style=self.config.option.tbstyle)
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ class BaseReport(object):
|
|||
def pytest_runtest_makereport(item, call):
|
||||
when = call.when
|
||||
keywords = dict([(x,1) for x in item.keywords])
|
||||
excinfo = call.excinfo
|
||||
if not call.excinfo:
|
||||
outcome = "passed"
|
||||
longrepr = None
|
||||
|
@ -312,8 +313,9 @@ class OutcomeException(Exception):
|
|||
""" OutcomeException and its subclass instances indicate and
|
||||
contain info about test and collection outcomes.
|
||||
"""
|
||||
def __init__(self, msg=None):
|
||||
def __init__(self, msg=None, pytrace=True):
|
||||
self.msg = msg
|
||||
self.pytrace = pytrace
|
||||
|
||||
def __repr__(self):
|
||||
if self.msg:
|
||||
|
@ -355,10 +357,10 @@ def skip(msg=""):
|
|||
raise Skipped(msg=msg)
|
||||
skip.Exception = Skipped
|
||||
|
||||
def fail(msg=""):
|
||||
def fail(msg="", pytrace=True):
|
||||
""" explicitely fail an currently-executing test with the given Message. """
|
||||
__tracebackhide__ = True
|
||||
raise Failed(msg=msg)
|
||||
raise Failed(msg=msg, pytrace=pytrace)
|
||||
fail.Exception = Failed
|
||||
|
||||
|
||||
|
|
|
@ -33,16 +33,40 @@ class UnitTestCase(pytest.Class):
|
|||
meth()
|
||||
|
||||
class TestCaseFunction(pytest.Function):
|
||||
_excinfo = None
|
||||
def setup(self):
|
||||
pass
|
||||
def teardown(self):
|
||||
pass
|
||||
def startTest(self, testcase):
|
||||
pass
|
||||
|
||||
def _addexcinfo(self, rawexcinfo):
|
||||
#__tracebackhide__ = True
|
||||
assert rawexcinfo
|
||||
try:
|
||||
self._excinfo = py.code.ExceptionInfo(rawexcinfo)
|
||||
except TypeError:
|
||||
try:
|
||||
try:
|
||||
l = py.std.traceback.format_exception(*rawexcinfo)
|
||||
l.insert(0, "NOTE: Incompatible Exception Representation, "
|
||||
"displaying natively:\n\n")
|
||||
pytest.fail("".join(l), pytrace=False)
|
||||
except (pytest.fail.Exception, KeyboardInterrupt):
|
||||
raise
|
||||
except:
|
||||
pytest.fail("ERROR: Unknown Incompatible Exception "
|
||||
"representation:\n%r" %(rawexcinfo,), pytrace=False)
|
||||
except pytest.fail.Exception:
|
||||
self._excinfo = py.code.ExceptionInfo()
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
|
||||
def addError(self, testcase, rawexcinfo):
|
||||
py.builtin._reraise(*rawexcinfo)
|
||||
self._addexcinfo(rawexcinfo)
|
||||
def addFailure(self, testcase, rawexcinfo):
|
||||
py.builtin._reraise(*rawexcinfo)
|
||||
self._addexcinfo(rawexcinfo)
|
||||
def addSuccess(self, testcase):
|
||||
pass
|
||||
def stopTest(self, testcase):
|
||||
|
@ -50,3 +74,11 @@ class TestCaseFunction(pytest.Function):
|
|||
def runtest(self):
|
||||
testcase = self.parent.obj(self.name)
|
||||
testcase(result=self)
|
||||
|
||||
@pytest.mark.tryfirst
|
||||
def pytest_runtest_makereport(item, call):
|
||||
if isinstance(item, TestCaseFunction):
|
||||
if item._excinfo:
|
||||
call.excinfo = item._excinfo
|
||||
item._excinfo = None
|
||||
del call.result
|
||||
|
|
|
@ -334,6 +334,17 @@ def test_pytest_fail():
|
|||
s = excinfo.exconly(tryshort=True)
|
||||
assert s.startswith("Failed")
|
||||
|
||||
def test_pytest_fail_notrace(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
def test_hello():
|
||||
pytest.fail("hello", pytrace=False)
|
||||
""")
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
"hello"
|
||||
])
|
||||
|
||||
def test_exception_printing_skip():
|
||||
try:
|
||||
pytest.skip("hello")
|
||||
|
|
|
@ -103,3 +103,65 @@ def test_class_setup(testdir):
|
|||
""")
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=3)
|
||||
|
||||
|
||||
@pytest.mark.multi(type=['Error', 'Failure'])
|
||||
def test_testcase_adderrorandfailure_defers(testdir, type):
|
||||
testdir.makepyfile("""
|
||||
from unittest import TestCase
|
||||
import pytest
|
||||
class MyTestCase(TestCase):
|
||||
def run(self, result):
|
||||
excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
|
||||
try:
|
||||
result.add%s(self, excinfo._excinfo)
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except:
|
||||
pytest.fail("add%s should not raise")
|
||||
def test_hello(self):
|
||||
pass
|
||||
""" % (type, type))
|
||||
result = testdir.runpytest()
|
||||
assert 'should not raise' not in result.stdout.str()
|
||||
|
||||
@pytest.mark.multi(type=['Error', 'Failure'])
|
||||
def test_testcase_custom_exception_info(testdir, type):
|
||||
testdir.makepyfile("""
|
||||
from unittest import TestCase
|
||||
import py, pytest
|
||||
class MyTestCase(TestCase):
|
||||
def run(self, result):
|
||||
excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
|
||||
# we fake an incompatible exception info
|
||||
from _pytest.monkeypatch import monkeypatch
|
||||
mp = monkeypatch()
|
||||
def t(*args):
|
||||
mp.undo()
|
||||
raise TypeError()
|
||||
mp.setattr(py.code, 'ExceptionInfo', t)
|
||||
try:
|
||||
excinfo = excinfo._excinfo
|
||||
result.add%(type)s(self, excinfo)
|
||||
finally:
|
||||
mp.undo()
|
||||
def test_hello(self):
|
||||
pass
|
||||
""" % locals())
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
"NOTE: Incompatible Exception Representation*",
|
||||
"*ZeroDivisionError*",
|
||||
"*1 failed*",
|
||||
])
|
||||
|
||||
def test_testcase_totally_incompatible_exception_info(testdir):
|
||||
item, = testdir.getitems("""
|
||||
from unittest import TestCase
|
||||
class MyTestCase(TestCase):
|
||||
def test_hello(self):
|
||||
pass
|
||||
""")
|
||||
item.addError(None, 42)
|
||||
excinfo = item._excinfo
|
||||
assert 'ERROR: Unknown Incompatible' in str(excinfo.getrepr())
|
||||
|
|
Loading…
Reference in New Issue