forked from pytest-dev/pytest
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
User Report
When running pytest with --pdb, unittest.TestCase.tearDown is executed for skipped tests, causing errors. In pytest==5.4.1, skipped tests remained skipped under --pdb, but in pytest==5.4.2, teardown runs and raises.
Minimal test:
import unittest
class MyTestCase(unittest.TestCase):
def setUp(self):
xxx
@unittest.skip("hello")
def test_one(self):
pass
def tearDown(self):
xxxEnvironment:
$ python --version
Python 3.6.10
$ pip freeze
attrs==19.3.0
importlib-metadata==1.6.0
more-itertools==8.2.0
packaging==20.3
pluggy==0.13.1
py==1.8.1
pyparsing==2.4.7
pytest==5.4.2
six==1.14.0
wcwidth==0.1.9
zipp==3.1.0
Behavior without --pdb:
$ pytest test_repro.py
============================= test session starts ==============================
platform linux -- Python 3.6.10, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: /srv/slapgrid/slappart3/srv/runner/project/repro_pytest
collected 1 item
test_repro.py s [100%]
============================== 1 skipped in 0.02s ==============================
Behavior with --pdb (unexpected teardown execution):
$ pytest --pdb test_repro.py
============================= test session starts ==============================
platform linux -- Python 3.6.10, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: /srv/slapgrid/slappart3/srv/runner/project/repro_pytest
collected 1 item
test_repro.py sE
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
self = <test_repro.MyTestCase testMethod=test_one>
def tearDown(self):
> xxx
E NameError: name 'xxx' is not defined
test_repro.py:10: NameError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> PDB post_mortem (IO-capturing turned off) >>>>>>>>>>>>>>>>>>
*** NameError: name 'execfile' is not defined
> /srv/slapgrid/slappart3/srv/runner/project/repro_pytest/test_repro.py(10)tearDown()
-> xxx
(Pdb) q
=========================== short test summary info ============================
ERROR test_repro.py::MyTestCase::test_one - NameError: name 'xxx' is not defined
!!!!!!!!!!!!!!!!!!! _pytest.outcomes.Exit: Quitting debugger !!!!!!!!!!!!!!!!!!!
========================= 1 skipped, 1 error in 1.83s ==========================
This appears to be a regression introduced between 5.4.1 and 5.4.2 (likely related to changes in pdb/skip/teardown logic, see PR pytest-dev#7151).
Researcher Specification (Emerson Gray)
Root cause:
- In
src/_pytest/unittest.py, when--pdbis active,TestCaseFunction.runtestdefersunittest.TestCase.tearDownby capturing the original intoself._explicit_tearDownand monkeypatchingtearDownto a no-op to preserve object state for debugging. TestCaseFunction.teardownthen unconditionally callsself._explicit_tearDown()if set.- For skipped tests (via
@unittest.skipor raisingunittest.SkipTest),TestCaseFunction.addSkipmaps this topytest.skip()and sets a skip tracking key (skipped_by_mark_key) inself._store. - However,
teardowndoes not check skip state; thus, even when skipped, deferredtearDownis invoked under--pdb.
Proposed fix (minimal and correct):
- Modify
src/_pytest/unittest.pyinTestCaseFunction.teardownto guard the invocation of deferredtearDownbased on skip state. - Pseudocode:
if self._explicit_tearDown is not None:
# Only call tearDown if the test was not skipped
if not self._store.get(skipped_by_mark_key, False):
self._explicit_tearDown()
self._explicit_tearDown = None
- Uses existing
skipped_by_mark_keyset by unittest skip handling and pytest marks; preserves behavior for non-skipped tests under--pdb.
Tests to add:
testing/test_unittest.py::test_unittest_skip_method_does_not_call_teardown_with_pdb- A
unittest.TestCasewith@unittest.skipon a method andtearDownthat would raise if called; run with--pdb; assert skipped and no teardown error.
- A
testing/test_unittest.py::test_unittest_setUp_raises_SkipTest_does_not_call_teardown_with_pdbsetUpraisesunittest.SkipTest;tearDownraises if called; run with--pdb; assert skipped.
testing/test_unittest.py::test_unittest_class_skip_does_not_call_teardown_with_pdb- Class-level
@unittest.skip;tearDownraises if called; assert skipped under--pdb.
- Class-level
Edge cases & interactions:
- Pytest skip marks: unaffected (runtest not executed, no deferred teardown).
- xfail: unchanged (
run=Falseskips in setup;expectedFailurestill runs and calls teardown). - PDB post-mortem on failures: unchanged; still enters pdb and calls teardown afterward for non-skipped tests.
We will implement this fix and add the tests, targeting the branch pytest-dev__pytest-7236.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels