summaryrefslogtreecommitdiff
path: root/src/_pytest/unittest.py
diff options
context:
space:
mode:
authorDaniel Hahler <git@thequod.de>2019-10-18 18:26:03 +0200
committerDaniel Hahler <git@thequod.de>2019-11-10 00:21:51 +0100
commit04f27d4eb469fb9c76fd2d100564a0f7d30028df (patch)
tree278d791fa163ca839b36dba5829419b22f2181c8 /src/_pytest/unittest.py
parent710e3c40e0e613a06eef62f58b3f7db9761ee868 (diff)
downloadpytest-04f27d4eb469fb9c76fd2d100564a0f7d30028df.tar.gz
unittest: do not use TestCase.debug() with `--pdb`
Fixes https://github.com/pytest-dev/pytest/issues/5991 Fixes https://github.com/pytest-dev/pytest/issues/3823 Ref: https://github.com/pytest-dev/pytest-django/issues/772 Ref: https://github.com/pytest-dev/pytest/pull/1890 Ref: https://github.com/pytest-dev/pytest-django/pull/782 - inject wrapped testMethod - adjust test_trial_error - add test for `--trace` with unittests
Diffstat (limited to 'src/_pytest/unittest.py')
-rw-r--r--src/_pytest/unittest.py60
1 files changed, 40 insertions, 20 deletions
diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py
index 11dc77cc4..bef209b0d 100644
--- a/src/_pytest/unittest.py
+++ b/src/_pytest/unittest.py
@@ -1,4 +1,5 @@
""" discovery and running of std-library "unittest" style tests. """
+import functools
import sys
import traceback
@@ -107,6 +108,7 @@ class TestCaseFunction(Function):
nofuncargs = True
_excinfo = None
_testcase = None
+ _need_tearDown = None
def setup(self):
self._testcase = self.parent.obj(self.name)
@@ -115,6 +117,8 @@ class TestCaseFunction(Function):
self._request._fillfixtures()
def teardown(self):
+ if self._need_tearDown:
+ self._testcase.tearDown()
self._testcase = None
self._obj = None
@@ -187,29 +191,45 @@ class TestCaseFunction(Function):
def stopTest(self, testcase):
pass
- def _handle_skip(self):
- # implements the skipping machinery (see #2137)
- # analog to pythons Lib/unittest/case.py:run
+ def runtest(self):
testMethod = getattr(self._testcase, self._testcase._testMethodName)
- if getattr(self._testcase.__class__, "__unittest_skip__", False) or getattr(
- testMethod, "__unittest_skip__", False
- ):
- # If the class or method was skipped.
- skip_why = getattr(
- self._testcase.__class__, "__unittest_skip_why__", ""
- ) or getattr(testMethod, "__unittest_skip_why__", "")
- self._testcase._addSkip(self, self._testcase, skip_why)
- return True
- return False
- def runtest(self):
- if self.config.pluginmanager.get_plugin("pdbinvoke") is None:
+ class _GetOutOf_testPartExecutor(KeyboardInterrupt):
+ """Helper exception to get out of unittests's testPartExecutor."""
+
+ unittest = sys.modules.get("unittest")
+
+ reraise = ()
+ if unittest:
+ reraise += (unittest.SkipTest,)
+
+ @functools.wraps(testMethod)
+ def wrapped_testMethod(*args, **kwargs):
+ try:
+ self.ihook.pytest_pyfunc_call(pyfuncitem=self)
+ except reraise:
+ raise
+ except Exception as exc:
+ expecting_failure_method = getattr(
+ 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:
+ raise
+
+ raise _GetOutOf_testPartExecutor(exc)
+
+ self._testcase._wrapped_testMethod = wrapped_testMethod
+ self._testcase._testMethodName = "_wrapped_testMethod"
+ try:
self._testcase(result=self)
- else:
- # disables tearDown and cleanups for post mortem debugging (see #1890)
- if self._handle_skip():
- return
- self._testcase.debug()
+ except _GetOutOf_testPartExecutor as exc:
+ raise exc.args[0] from exc.args[0]
def _prunetraceback(self, excinfo):
Function._prunetraceback(self, excinfo)