summaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorRonny Pfannschmidt <opensource@ronnypfannschmidt.de>2018-04-10 07:15:29 +0200
committerGitHub <noreply@github.com>2018-04-10 07:15:29 +0200
commit2241c98b18cbc2c9ac26b94a07872610cfb36da3 (patch)
tree9512a04ae38b44717c2db6c90a71b6fddfa94c8e /testing
parent715337011be81c721a35d0056a352d7cdc2731ec (diff)
parent0762666bd116d92b55f746cde8e25e965ea2912b (diff)
downloadpytest-2241c98b18cbc2c9ac26b94a07872610cfb36da3.tar.gz
Merge pull request #3331 from tonybaloney/breakpoint_support
Support for the new builtin breakpoint function in Python 3.7
Diffstat (limited to 'testing')
-rw-r--r--testing/test_pdb.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/testing/test_pdb.py b/testing/test_pdb.py
index 445cafcc5..85817f79b 100644
--- a/testing/test_pdb.py
+++ b/testing/test_pdb.py
@@ -1,11 +1,16 @@
from __future__ import absolute_import, division, print_function
import sys
import platform
+import os
import _pytest._code
+from _pytest.debugging import SUPPORTS_BREAKPOINT_BUILTIN
import pytest
+_ENVIRON_PYTHONBREAKPOINT = os.environ.get('PYTHONBREAKPOINT', '')
+
+
def runpdb_and_get_report(testdir, source):
p = testdir.makepyfile(source)
result = testdir.runpytest_inprocess("--pdb", p)
@@ -33,6 +38,30 @@ def custom_pdb_calls():
return called
+@pytest.fixture
+def custom_debugger_hook():
+ called = []
+
+ # install dummy debugger class and track which methods were called on it
+ class _CustomDebugger(object):
+ def __init__(self, *args, **kwargs):
+ called.append("init")
+
+ def reset(self):
+ called.append("reset")
+
+ def interaction(self, *args):
+ called.append("interaction")
+
+ def set_trace(self, frame):
+ print("**CustomDebugger**")
+ called.append("set_trace")
+
+ _pytest._CustomDebugger = _CustomDebugger
+ yield called
+ del _pytest._CustomDebugger
+
+
class TestPDB(object):
@pytest.fixture
@@ -470,3 +499,122 @@ class TestPDB(object):
child.expect('custom set_trace>')
self.flush(child)
+
+
+class TestDebuggingBreakpoints(object):
+
+ def test_supports_breakpoint_module_global(self):
+ """
+ Test that supports breakpoint global marks on Python 3.7+ and not on
+ CPython 3.5, 2.7
+ """
+ if sys.version_info.major == 3 and sys.version_info.minor >= 7:
+ assert SUPPORTS_BREAKPOINT_BUILTIN is True
+ if sys.version_info.major == 3 and sys.version_info.minor == 5:
+ assert SUPPORTS_BREAKPOINT_BUILTIN is False
+ if sys.version_info.major == 2 and sys.version_info.minor == 7:
+ assert SUPPORTS_BREAKPOINT_BUILTIN is False
+
+ @pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
+ @pytest.mark.parametrize('arg', ['--pdb', ''])
+ def test_sys_breakpointhook_configure_and_unconfigure(self, testdir, arg):
+ """
+ Test that sys.breakpointhook is set to the custom Pdb class once configured, test that
+ hook is reset to system value once pytest has been unconfigured
+ """
+ testdir.makeconftest("""
+ import sys
+ from pytest import hookimpl
+ from _pytest.debugging import pytestPDB
+
+ def pytest_configure(config):
+ config._cleanup.append(check_restored)
+
+ def check_restored():
+ assert sys.breakpointhook == sys.__breakpointhook__
+
+ def test_check():
+ assert sys.breakpointhook == pytestPDB.set_trace
+ """)
+ testdir.makepyfile("""
+ def test_nothing(): pass
+ """)
+ args = (arg,) if arg else ()
+ result = testdir.runpytest_subprocess(*args)
+ result.stdout.fnmatch_lines([
+ '*1 passed in *',
+ ])
+
+ @pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
+ def test_pdb_custom_cls(self, testdir, custom_debugger_hook):
+ p1 = testdir.makepyfile("""
+ def test_nothing():
+ breakpoint()
+ """)
+ result = testdir.runpytest_inprocess(
+ "--pdb", "--pdbcls=_pytest:_CustomDebugger", p1)
+ result.stdout.fnmatch_lines([
+ "*CustomDebugger*",
+ "*1 passed*",
+ ])
+ assert custom_debugger_hook == ["init", "set_trace"]
+
+ @pytest.mark.parametrize('arg', ['--pdb', ''])
+ @pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
+ def test_environ_custom_class(self, testdir, custom_debugger_hook, arg):
+ testdir.makeconftest("""
+ import os
+ import sys
+
+ os.environ['PYTHONBREAKPOINT'] = '_pytest._CustomDebugger.set_trace'
+
+ def pytest_configure(config):
+ config._cleanup.append(check_restored)
+
+ def check_restored():
+ assert sys.breakpointhook == sys.__breakpointhook__
+
+ def test_check():
+ import _pytest
+ assert sys.breakpointhook is _pytest._CustomDebugger.set_trace
+ """)
+ testdir.makepyfile("""
+ def test_nothing(): pass
+ """)
+ args = (arg,) if arg else ()
+ result = testdir.runpytest_subprocess(*args)
+ result.stdout.fnmatch_lines([
+ '*1 passed in *',
+ ])
+
+ @pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
+ @pytest.mark.skipif(not _ENVIRON_PYTHONBREAKPOINT == '', reason="Requires breakpoint() default value")
+ def test_sys_breakpoint_interception(self, testdir):
+ p1 = testdir.makepyfile("""
+ def test_1():
+ breakpoint()
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("test_1")
+ child.expect("(Pdb)")
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert "1 failed" in rest
+ assert "reading from stdin while output" not in rest
+ TestPDB.flush(child)
+
+ @pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
+ def test_pdb_not_altered(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pdb
+ def test_1():
+ pdb.set_trace()
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("test_1")
+ child.expect("(Pdb)")
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert "1 failed" in rest
+ assert "reading from stdin while output" not in rest
+ TestPDB.flush(child)