From d1c725078a8c2fccfc573772e1944b9fe2a902e6 Mon Sep 17 00:00:00 2001 From: mbyt Date: Mon, 30 Jan 2017 21:20:12 +0100 Subject: [PATCH 1/3] Allow to skip unittests if --pdb active closes #2137 --- CHANGELOG.rst | 7 ++++++- _pytest/unittest.py | 14 ++++++++++++-- testing/test_pdb.py | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 006c0ed0f3d..7f24a32829a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,8 @@ 3.0.7 (unreleased) ======================= -* +* Fix regression, pytest now skips unittest correctly if run with ``--pdb`` + (`#2137`_). Thanks to `@gst`_ for the report and `@mbyt`_ for the PR. * @@ -9,6 +10,10 @@ * +.. _@gst: https://github.com/gst + +.. _#2137: https://github.com/pytest-dev/pytest/issues/2137 + 3.0.6 (2017-01-22) ================== diff --git a/_pytest/unittest.py b/_pytest/unittest.py index 73224010b21..4d303e7e300 100644 --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -65,7 +65,6 @@ def collect(self): yield TestCaseFunction('runTest', parent=self) - class TestCaseFunction(pytest.Function): _excinfo = None @@ -157,9 +156,20 @@ def runtest(self): self._testcase(result=self) else: # disables tearDown and cleanups for post mortem debugging (see #1890) + # but still implements the skipping machinery (see #2137) + 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__', '')) + try: + self._testcase._addSkip(self, self._testcase, skip_why) + except TypeError: # PY2 + self._testcase._addSkip(self, skip_why) + return self._testcase.debug() - def _prunetraceback(self, excinfo): pytest.Function._prunetraceback(self, excinfo) traceback = excinfo.traceback.filter( diff --git a/testing/test_pdb.py b/testing/test_pdb.py index df58dad8729..8a2efdb87f5 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -106,6 +106,20 @@ def test_false(self): assert 'debug.me' in rest self.flush(child) + def test_pdb_unittest_skip(self, testdir): + p1 = testdir.makepyfile(""" + import unittest + @unittest.skipIf(True, 'Skipping also with pdb active') + class MyTestCase(unittest.TestCase): + def test_one(self): + assert 0 + """) + child = testdir.spawn_pytest("-rs --pdb %s" % p1) + child.expect('Skipping also with pdb active') + child.expect('1 skipped in') + child.sendeof() + self.flush(child) + def test_pdb_interaction_capture(self, testdir): p1 = testdir.makepyfile(""" def test_1(): From 36b6f17727589defa28101142009410c9c771289 Mon Sep 17 00:00:00 2001 From: mbyt Date: Tue, 31 Jan 2017 21:03:49 +0100 Subject: [PATCH 2/3] fixing code-style, keep flake8 happy --- _pytest/unittest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_pytest/unittest.py b/_pytest/unittest.py index 4d303e7e300..0126ff83833 100644 --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -161,8 +161,8 @@ def runtest(self): 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__', '')) + skip_why = (getattr(self._testcase.__class__, '__unittest_skip_why__', '') or + getattr(testMethod, '__unittest_skip_why__', '')) try: self._testcase._addSkip(self, self._testcase, skip_why) except TypeError: # PY2 From ad56cd8027756a8bc1aa83402bbfffeae3520129 Mon Sep 17 00:00:00 2001 From: mbyt Date: Thu, 2 Feb 2017 05:01:51 +0100 Subject: [PATCH 3/3] extract a _handle_skip method, secure PY2 branch --- _pytest/unittest.py | 30 +++++++++++++++++++----------- testing/test_pdb.py | 1 + 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/_pytest/unittest.py b/_pytest/unittest.py index 0126ff83833..34eb9885bee 100644 --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -151,22 +151,30 @@ def addSuccess(self, testcase): def stopTest(self, testcase): pass + def _handle_skip(self): + # implements the skipping machinery (see #2137) + # analog to pythons Lib/unittest/case.py:run + 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__', '')) + try: # PY3, unittest2 on PY2 + self._testcase._addSkip(self, self._testcase, skip_why) + except TypeError: # PY2 + if sys.version_info[0] != 2: + raise + self._testcase._addSkip(self, skip_why) + return True + return False + def runtest(self): if self.config.pluginmanager.get_plugin("pdbinvoke") is None: self._testcase(result=self) else: # disables tearDown and cleanups for post mortem debugging (see #1890) - # but still implements the skipping machinery (see #2137) - 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__', '')) - try: - self._testcase._addSkip(self, self._testcase, skip_why) - except TypeError: # PY2 - self._testcase._addSkip(self, skip_why) + if self._handle_skip(): return self._testcase.debug() diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 8a2efdb87f5..52a75d916b8 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -107,6 +107,7 @@ def test_false(self): self.flush(child) def test_pdb_unittest_skip(self, testdir): + """Test for issue #2137""" p1 = testdir.makepyfile(""" import unittest @unittest.skipIf(True, 'Skipping also with pdb active')