No need to call tearDown on expected failures

- Isolate logic for getting expected exceptions
- Use original method name, as users see it when entering the debugger
This commit is contained in:
Bruno Oliveira 2019-11-12 12:47:03 -03:00
parent 04f27d4eb4
commit f7b1de70c0
1 changed files with 19 additions and 23 deletions

View File

@ -108,7 +108,6 @@ class TestCaseFunction(Function):
nofuncargs = True nofuncargs = True
_excinfo = None _excinfo = None
_testcase = None _testcase = None
_need_tearDown = None
def setup(self): def setup(self):
self._testcase = self.parent.obj(self.name) self._testcase = self.parent.obj(self.name)
@ -117,8 +116,6 @@ class TestCaseFunction(Function):
self._request._fillfixtures() self._request._fillfixtures()
def teardown(self): def teardown(self):
if self._need_tearDown:
self._testcase.tearDown()
self._testcase = None self._testcase = None
self._obj = None self._obj = None
@ -191,45 +188,44 @@ class TestCaseFunction(Function):
def stopTest(self, testcase): def stopTest(self, testcase):
pass pass
def _expecting_failure(self, test_method) -> bool:
"""Return True if the given unittest method (or the entire class) is marked
with @expectedFailure"""
expecting_failure_method = getattr(
test_method, "__unittest_expecting_failure__", False
)
expecting_failure_class = getattr(self, "__unittest_expecting_failure__", False)
return bool(expecting_failure_class or expecting_failure_method)
def runtest(self): def runtest(self):
import unittest
testMethod = getattr(self._testcase, self._testcase._testMethodName) testMethod = getattr(self._testcase, self._testcase._testMethodName)
class _GetOutOf_testPartExecutor(KeyboardInterrupt): class _GetOutOf_testPartExecutor(KeyboardInterrupt):
"""Helper exception to get out of unittests's testPartExecutor.""" """Helper exception to get out of unittests's testPartExecutor (see TestCase.run)."""
unittest = sys.modules.get("unittest")
reraise = ()
if unittest:
reraise += (unittest.SkipTest,)
@functools.wraps(testMethod) @functools.wraps(testMethod)
def wrapped_testMethod(*args, **kwargs): def wrapped_testMethod(*args, **kwargs):
"""Wrap the original method to call into pytest's machinery, so other pytest
features can have a chance to kick in (notably --pdb)"""
try: try:
self.ihook.pytest_pyfunc_call(pyfuncitem=self) self.ihook.pytest_pyfunc_call(pyfuncitem=self)
except reraise: except unittest.SkipTest:
raise raise
except Exception as exc: except Exception as exc:
expecting_failure_method = getattr( expecting_failure = self._expecting_failure(testMethod)
testMethod, "__unittest_expecting_failure__", False
)
expecting_failure_class = getattr(
self, "__unittest_expecting_failure__", False
)
expecting_failure = expecting_failure_class or expecting_failure_method
self._need_tearDown = True
if expecting_failure: if expecting_failure:
raise raise
raise _GetOutOf_testPartExecutor(exc) raise _GetOutOf_testPartExecutor(exc)
self._testcase._wrapped_testMethod = wrapped_testMethod setattr(self._testcase, self._testcase._testMethodName, wrapped_testMethod)
self._testcase._testMethodName = "_wrapped_testMethod"
try: try:
self._testcase(result=self) self._testcase(result=self)
except _GetOutOf_testPartExecutor as exc: except _GetOutOf_testPartExecutor as exc:
raise exc.args[0] from exc.args[0] raise exc.args[0] from exc.args[0]
finally:
delattr(self._testcase, self._testcase._testMethodName)
def _prunetraceback(self, excinfo): def _prunetraceback(self, excinfo):
Function._prunetraceback(self, excinfo) Function._prunetraceback(self, excinfo)