Skip to content

Commit

Permalink
Merge pull request #34 from nicoddemus/pdb-support
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoddemus authored Dec 13, 2020
2 parents 96fc692 + 8dad536 commit ce342fe
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CHANGELOG
=========

0.4.0 (2020-12-13)
------------------

* Add support for ``--pdb`` (`#22`_).

.. _#22: https://github.com/pytest-dev/pytest-subtests/issues/22

0.3.2 (2020-08-01)
------------------

Expand Down
15 changes: 15 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ Requirements
* ``Python`` >= 3.5.
* ``pytest`` >= 4.4.

pytest 6.2+
^^^^^^^^^^^

``pytest 6.2`` now issues a warning when internal classes are used by third-party code,
which is the case for ``pytest-subtests`` which needs to use some internal classes
to integrate with other pytest features (such as capturing and debugging).

For now users can ignore those warnings by adding this to their configuration file:

.. code-block:: ini
[pytest]
filterwarnings =
ignore:A private pytest class or function was used.:PytestDeprecationWarning
Installation
------------

Expand Down
10 changes: 10 additions & 0 deletions pytest_subtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from _pytest.outcomes import OutcomeException
from _pytest.reports import TestReport
from _pytest.runner import CallInfo
from _pytest.runner import check_interactive_exception
from _pytest.unittest import TestCaseFunction

if sys.version_info[:2] < (3, 7):
Expand Down Expand Up @@ -80,6 +81,10 @@ def _addSubTest(self, test_case, test, exc_info):
sub_report = SubTestReport.from_item_and_call(item=self, call=call_info)
sub_report.context = SubTestContext(msg, dict(test.params))
self.ihook.pytest_runtest_logreport(report=sub_report)
if check_interactive_exception(call_info, sub_report):
self.ihook.pytest_exception_interact(
node=self, call=call_info, report=sub_report
)


def pytest_configure(config):
Expand Down Expand Up @@ -174,6 +179,11 @@ def test(self, msg=None, **kwargs):
with self.suspend_capture_ctx():
self.ihook.pytest_runtest_logreport(report=sub_report)

if check_interactive_exception(call_info, sub_report):
self.ihook.pytest_exception_interact(
node=self.item, call=call_info, report=sub_report
)


def make_call_info(exc_info, *, start, stop, duration, when):
try:
Expand Down
74 changes: 74 additions & 0 deletions tests/test_subtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
import pytest


@pytest.fixture(autouse=True)
def ignore_private_class_warning(testdir):
"""
Make every test in this file ignore the warning about using private pytest classes;
It is a risk we are willing to take in this plugin.
"""
testdir.makeini(
"""
[pytest]
filterwarnings = ignore:A private pytest class
"""
)


@pytest.mark.parametrize("mode", ["normal", "xdist"])
class TestFixture:
"""
Expand Down Expand Up @@ -307,3 +321,63 @@ def test(subtests, {fixture}):
result.stdout.fnmatch_lines(
["*1 passed*",]
)


class TestDebugging:
"""Check --pdb support for subtests fixture and TestCase.subTest."""

class _FakePdb:
"""
Fake debugger class implementation that tracks which methods were called on it.
"""

quitting = False
calls = []

def __init__(self, *args, **kwargs):
self.calls.append("init")

def reset(self):
self.calls.append("reset")

def interaction(self, *args):
self.calls.append("interaction")

@pytest.fixture(autouse=True)
def cleanup_calls(self):
self._FakePdb.calls.clear()

def test_pdb_fixture(self, testdir, monkeypatch):
testdir.makepyfile(
"""
def test(subtests):
with subtests.test():
assert 0
"""
)
self.runpytest_and_check_pdb(testdir, monkeypatch)

def test_pdb_unittest(self, testdir, monkeypatch):
testdir.makepyfile(
"""
from unittest import TestCase
class Test(TestCase):
def test(self):
with self.subTest():
assert 0
"""
)
self.runpytest_and_check_pdb(testdir, monkeypatch)

def runpytest_and_check_pdb(self, testdir, monkeypatch):
# Install the fake pdb implementation in pytest_subtests so we can reference
# it in the command line (any module would do).
import pytest_subtests

monkeypatch.setattr(pytest_subtests, "_CustomPdb", self._FakePdb, raising=False)
result = testdir.runpytest("--pdb", "--pdbcls=pytest_subtests:_CustomPdb")

# Ensure pytest entered in debugging mode when encountering the failing
# assert.
result.stdout.fnmatch_lines("*entering PDB*")
assert self._FakePdb.calls == ["init", "reset", "interaction"]

0 comments on commit ce342fe

Please sign in to comment.