-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
gh-79871: IDLE - Fix and test debugger module #11451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 10 commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
bbb58e8
start setting up tests for the Idb module
tonybaloney 525efbc
handle NoneType in frame.f_back (first frame in session) and call bdb…
tonybaloney 83aeefa
add a test for Idb to ensure calling super. Add a test to check the h…
tonybaloney d01dcdb
add test for user_exception to validate passing of exc_info to gui in…
tonybaloney 6a123ef
add tests for in_rpc_code to catch various frame file names
tonybaloney e5e882c
add some PEP8 compliant line breaks
tonybaloney 35915da
setup tests for the debugger.Debugger class
tonybaloney dbb5c7e
add tests for run with and without an idb instance set on init
tonybaloney 2929019
add tests for interaction, which are currently demonstrating a bug in…
tonybaloney bbe4300
Bdb expects an instance attribute called 'botframe', which is set by …
tonybaloney 4957496
remove empty single line comments
tonybaloney fbf1cac
add tests for the basic operations
tonybaloney 2b42337
finished tests for Debugger
tonybaloney 56741f1
add a constructor for MockFrameType to condense the code
tonybaloney 8d015ce
add tests for show_source and load_stack for the StackViewer class
tonybaloney 4807556
remove line comment
tonybaloney 88e5f91
📜🤖 Added by blurb_it.
blurb-it[bot] 0df2512
fixed references to .assertEquals, moved code into setup and teardown…
tonybaloney dfe6db9
cleanupm stackviewer tests and use Tk instance
tonybaloney 2b9a43a
untoggle the gui requirement
tonybaloney 5ae4060
Change the single-line docstrings to comments
tonybaloney 14b908f
Removed the 2 interaction tests because they cause the UI to wait for…
tonybaloney ae491f4
Fix the test assertions and use stacked frames when testing debugging…
tonybaloney bc28ced
Make the test vaguer so that if the coverage checks pass it doesn't i…
tonybaloney 9333fcf
Clean up attributes in memory and split tests between those which nee…
tonybaloney 046fe00
Merge branch 'main' into idlelib_tests
terryjreedy daa2015
Update Misc/NEWS.d/next/IDLE/2019-01-07-06-18-25.bpo-35668.JimxP5.rst
terryjreedy 37afb53
Update 2019-01-07-06-18-25.bpo-35668.JimxP5.rst
terryjreedy f4c3c00
Merge remote-tracking branch 'upstream/main' into pr_11451
terryjreedy e9d0e4e
Add comment to stackviewer.
terryjreedy 3b97b55
Add debugger module docstrings and revise those for Idb.
terryjreedy d989bfa
Fix test failures by using 'assert_called_once_with'.
terryjreedy 22e8249
Remove duplicate test.
terryjreedy 2611447
Merge remote-tracking branch 'upstream/main' into pr_11451
terryjreedy f9f1a22
Remove added 'botframe' initialization as very likely not needed.
terryjreedy a202f4f
Move function frame2message to module level.
terryjreedy 597cbba
IDLE style is no newline to start docstring.
terryjreedy 0a53cd1
Change 'doc string' to 'Doc string.'
terryjreedy 114d686
Remove unneeded Ibd setups and teardowns.
terryjreedy 1c1107d
Polish IdbTest.
terryjreedy ed58072
Make in_rpc_code a module function, like frame2message.
terryjreedy d541302
Add FunctionTest
terryjreedy df1936f
Refactor IdbTest.
terryjreedy fedfbc0
FunctionTest comment
terryjreedy a731e63
Use False, True for Debugger().interacting.
terryjreedy 9eb6548
Modify Debugger tests
terryjreedy 0454ea5
Import Mock and patch, refactor to run many tests without gui.
terryjreedy 63008a5
Put no-gui tests first, fix breakpoints, work on gui tests.
terryjreedy fe14bb8
Tests pass.
terryjreedy fd7e259
Merge branch 'main' into idlelib_tests
terryjreedy 5fe9868
ws
terryjreedy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,11 @@ | |
|
||
from idlelib import debugger | ||
import unittest | ||
from unittest import mock | ||
from test.support import requires | ||
requires('gui') | ||
# requires('gui') | ||
tonybaloney marked this conversation as resolved.
Show resolved
Hide resolved
|
||
from tkinter import Tk | ||
from textwrap import dedent | ||
|
||
|
||
class NameSpaceTest(unittest.TestCase): | ||
|
@@ -23,7 +25,218 @@ def test_init(self): | |
debugger.NamespaceViewer(self.root, 'Test') | ||
|
||
|
||
# Other classes are Idb, Debugger, and StackViewer. | ||
class MockFrameType(object): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IDLE tests aren't backported to 2.7, so you don't need to include object when defining a class. |
||
"""Reflection of the types.FrameType.""" | ||
f_back = None | ||
f_builtins = None | ||
f_code = None | ||
f_globals = None | ||
f_lasti = None | ||
f_lineno = None | ||
f_locals = None | ||
f_restricted = 0 | ||
f_trace = None | ||
|
||
def __init__(self): | ||
pass | ||
|
||
|
||
class IdbTest(unittest.TestCase): | ||
|
||
def test_init_runs_bdb_init(self): | ||
"""Test that Idb calls the base Bdb __init__.""" | ||
idb = debugger.Idb(None) | ||
assert idb.gui is None | ||
assert hasattr(idb, 'breaks') | ||
tonybaloney marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def test_user_line_basic_frame(self): | ||
"""Test that .user_line() creates a string message for a frame.""" | ||
|
||
# Create a test code object to simulate a debug session. | ||
test_code = dedent(""" | ||
i = 1 | ||
i += 2 | ||
if i == 3: | ||
print(i) | ||
""") | ||
code_obj = compile(test_code, | ||
'test_user_line_basic_frame.py', | ||
mode='exec') | ||
|
||
# Create 2 test frames for lines 1 and 2 of the test code. | ||
test_frame1 = MockFrameType() | ||
test_frame1.f_code = code_obj | ||
test_frame1.f_lineno = 1 | ||
|
||
test_frame2 = MockFrameType() | ||
test_frame2.f_code = code_obj | ||
test_frame2.f_lineno = 2 | ||
test_frame2.f_back = test_frame1 | ||
|
||
gui = mock.Mock() | ||
gui.interaction = mock.Mock() | ||
|
||
idb = debugger.Idb(gui) | ||
tonybaloney marked this conversation as resolved.
Show resolved
Hide resolved
|
||
idb.user_line(test_frame2) | ||
|
||
assert not idb.in_rpc_code(test_frame2) | ||
gui.interaction.assert_called_once() | ||
gui.interaction.assert_called_with('test_user_line_basic_frame.py:2: <module>()', test_frame2) | ||
|
||
def test_user_exception(self): | ||
"""Test that .user_exception() creates a string message for a frame.""" | ||
|
||
# Create a test code object to simulate a debug session. | ||
test_code = dedent(""" | ||
i = 1 | ||
i += 2 | ||
if i == 3: | ||
print(i) | ||
""") | ||
code_obj = compile(test_code, | ||
'test_user_exception.py', | ||
mode='exec') | ||
|
||
# Create 1 test frame | ||
test_frame1 = MockFrameType() | ||
test_frame1.f_code = code_obj | ||
test_frame1.f_lineno = 1 | ||
|
||
# Example from sys.exc_info() | ||
test_exc_info = (type(ValueError), ValueError(), None) | ||
|
||
gui = mock.Mock() | ||
gui.interaction = mock.Mock() | ||
|
||
idb = debugger.Idb(gui) | ||
idb.user_exception(test_frame1, test_exc_info) | ||
|
||
assert not idb.in_rpc_code(test_frame1) | ||
gui.interaction.assert_called_once() | ||
gui.interaction.assert_called_with('test_user_exception.py:1: <module>()', test_frame1, test_exc_info) | ||
|
||
def test_in_rpc_code_rpc_py(self): | ||
"""Test that .in_rpc_code detects position of rpc.py.""" | ||
|
||
# Create a test code object to simulate a debug session. | ||
test_code = dedent(""" | ||
i = 1 | ||
i += 2 | ||
if i == 3: | ||
print(i) | ||
""") | ||
code_obj = compile(test_code, | ||
'rpc.py', | ||
mode='exec') | ||
|
||
# Create 1 test frame | ||
test_frame = MockFrameType() | ||
test_frame.f_code = code_obj | ||
test_frame.f_lineno = 1 | ||
|
||
gui = mock.Mock() | ||
gui.interaction = mock.Mock() | ||
|
||
idb = debugger.Idb(gui) | ||
|
||
assert idb.in_rpc_code(test_frame) | ||
|
||
def test_in_rpc_code_debugger_star_dot_py(self): | ||
"""Test that .in_rpc_code detects position of idlelib/debugger*.py.""" | ||
|
||
# Create a test code object to simulate a debug session. | ||
for filename in ('idlelib/debugger.py', 'idlelib/debugger_r.py'): | ||
test_code = dedent(""" | ||
i = 1 | ||
i += 2 | ||
if i == 3: | ||
print(i) | ||
""") | ||
code_obj = compile(test_code, | ||
filename, | ||
mode='exec') | ||
|
||
# Create 2 test frames | ||
test_frame = MockFrameType() | ||
test_frame.f_code = code_obj | ||
test_frame.f_lineno = 1 | ||
|
||
test_frame2 = MockFrameType() | ||
test_frame2.f_code = code_obj | ||
test_frame2.f_lineno = 2 | ||
test_frame2.f_back = test_frame | ||
|
||
gui = mock.Mock() | ||
gui.interaction = mock.Mock() | ||
|
||
idb = debugger.Idb(gui) | ||
|
||
assert not idb.in_rpc_code(test_frame2) | ||
|
||
|
||
def make_pyshell_mock(): | ||
tonybaloney marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""Factory for generating test fixtures of PyShell.""" | ||
pyshell = mock.Mock() | ||
pyshell.root = None | ||
return pyshell | ||
|
||
|
||
class DebuggerTest(unittest.TestCase): | ||
"""Tests for the idlelib.debugger.Debugger class.""" | ||
|
||
tonybaloney marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def test_setup_debugger(self): | ||
"""Test that Debugger can be instantiated with a mock PyShell.""" | ||
pyshell = make_pyshell_mock() | ||
test_debugger = debugger.Debugger(pyshell) | ||
|
||
assert test_debugger.pyshell == pyshell | ||
assert test_debugger.frame is None | ||
|
||
def test_run_debugger_with_idb(self): | ||
"""Test Debugger.run() with an Idb instance.""" | ||
mock_idb = mock.Mock() # Mocked debugger.Idb | ||
test_debugger = debugger.Debugger(make_pyshell_mock(), idb=mock_idb) | ||
test_debugger.run(1, 'two') | ||
mock_idb.run.assert_called_once() | ||
mock_idb.run.called_with(1, 'two') | ||
assert test_debugger.interacting == 0 | ||
|
||
def test_run_debugger_no_idb(self): | ||
"""Test Debugger.run() with no Idb instance.""" | ||
test_debugger = debugger.Debugger(make_pyshell_mock(), idb=None) | ||
assert test_debugger.idb is not None | ||
test_debugger.idb.run = mock.Mock() | ||
test_debugger.run(1, 'two') | ||
test_debugger.idb.run.assert_called_once() | ||
test_debugger.idb.run.called_with(1, 'two') | ||
assert test_debugger.interacting == 0 | ||
|
||
def test_close(self): | ||
"""Test closing the window in an idle state.""" | ||
pyshell = make_pyshell_mock() | ||
test_debugger = debugger.Debugger(pyshell) | ||
tonybaloney marked this conversation as resolved.
Show resolved
Hide resolved
|
||
test_debugger.close() | ||
pyshell.close_debugger.assert_called_once() | ||
|
||
def test_close_whilst_interacting(self): | ||
"""Test closing the window in an interactive state.""" | ||
pyshell = make_pyshell_mock() | ||
test_debugger = debugger.Debugger(pyshell) | ||
test_debugger.interacting = 1 | ||
test_debugger.close() | ||
pyshell.close_debugger.assert_not_called() | ||
|
||
def test_interaction_with_message_and_frame(self): | ||
test_message = "testing 1234.." | ||
test_frame = MockFrameType() | ||
|
||
pyshell = make_pyshell_mock() | ||
test_debugger = debugger.Debugger(pyshell) | ||
|
||
# Patch out the status label so we can check messages | ||
test_debugger.status = mock.Mock() | ||
test_debugger.interaction(test_message, test_frame) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main(verbosity=2) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.