update
This commit is contained in:
237
.CondaPkg/env/Lib/idlelib/idle_test/htest.py
vendored
237
.CondaPkg/env/Lib/idlelib/idle_test/htest.py
vendored
@@ -1,38 +1,36 @@
|
||||
'''Run human tests of Idle's window, dialog, and popup widgets.
|
||||
"""Run human tests of Idle's window, dialog, and popup widgets.
|
||||
|
||||
run(*tests)
|
||||
Create a master Tk window. Within that, run each callable in tests
|
||||
after finding the matching test spec in this file. If tests is empty,
|
||||
run an htest for each spec dict in this file after finding the matching
|
||||
callable in the module named in the spec. Close the window to skip or
|
||||
end the test.
|
||||
run(*tests) Create a master Tk() htest window. Within that, run each
|
||||
callable in tests after finding the matching test spec in this file. If
|
||||
tests is empty, run an htest for each spec dict in this file after
|
||||
finding the matching callable in the module named in the spec. Close
|
||||
the master window to end testing.
|
||||
|
||||
In a tested module, let X be a global name bound to a callable (class
|
||||
or function) whose .__name__ attribute is also X (the usual situation).
|
||||
The first parameter of X must be 'parent'. When called, the parent
|
||||
argument will be the root window. X must create a child Toplevel
|
||||
window (or subclass thereof). The Toplevel may be a test widget or
|
||||
dialog, in which case the callable is the corresponding class. Or the
|
||||
Toplevel may contain the widget to be tested or set up a context in
|
||||
which a test widget is invoked. In this latter case, the callable is a
|
||||
wrapper function that sets up the Toplevel and other objects. Wrapper
|
||||
function names, such as _editor_window', should start with '_'.
|
||||
In a tested module, let X be a global name bound to a callable (class or
|
||||
function) whose .__name__ attribute is also X (the usual situation). The
|
||||
first parameter of X must be 'parent' or 'master'. When called, the
|
||||
first argument will be the root window. X must create a child
|
||||
Toplevel(parent/master) (or subclass thereof). The Toplevel may be a
|
||||
test widget or dialog, in which case the callable is the corresponding
|
||||
class. Or the Toplevel may contain the widget to be tested or set up a
|
||||
context in which a test widget is invoked. In this latter case, the
|
||||
callable is a wrapper function that sets up the Toplevel and other
|
||||
objects. Wrapper function names, such as _editor_window', should start
|
||||
with '_' and be lowercase.
|
||||
|
||||
|
||||
End the module with
|
||||
|
||||
if __name__ == '__main__':
|
||||
<unittest, if there is one>
|
||||
<run unittest.main with 'exit=False'>
|
||||
from idlelib.idle_test.htest import run
|
||||
run(X)
|
||||
run(callable) # There could be multiple comma-separated callables.
|
||||
|
||||
To have wrapper functions and test invocation code ignored by coveragepy
|
||||
reports, put '# htest #' on the def statement header line.
|
||||
|
||||
def _wrapper(parent): # htest #
|
||||
|
||||
Also make sure that the 'if __name__' line matches the above. Then have
|
||||
make sure that .coveragerc includes the following.
|
||||
To have wrapper functions ignored by coverage reports, tag the def
|
||||
header like so: "def _wrapper(parent): # htest #". Use the same tag
|
||||
for htest lines in widget code. Make sure that the 'if __name__' line
|
||||
matches the above. Then have make sure that .coveragerc includes the
|
||||
following:
|
||||
|
||||
[report]
|
||||
exclude_lines =
|
||||
@@ -46,7 +44,7 @@ To run any X, this file must contain a matching instance of the
|
||||
following template, with X.__name__ prepended to '_spec'.
|
||||
When all tests are run, the prefix is use to get X.
|
||||
|
||||
_spec = {
|
||||
callable_spec = {
|
||||
'file': '',
|
||||
'kwds': {'title': ''},
|
||||
'msg': ""
|
||||
@@ -54,16 +52,16 @@ _spec = {
|
||||
|
||||
file (no .py): run() imports file.py.
|
||||
kwds: augmented with {'parent':root} and passed to X as **kwds.
|
||||
title: an example kwd; some widgets need this, delete if not.
|
||||
title: an example kwd; some widgets need this, delete line if not.
|
||||
msg: master window hints about testing the widget.
|
||||
|
||||
|
||||
Modules and classes not being tested at the moment:
|
||||
pyshell.PyShellEditorWindow
|
||||
debugger.Debugger
|
||||
autocomplete_w.AutoCompleteWindow
|
||||
outwin.OutputWindow (indirectly being tested with grep test)
|
||||
'''
|
||||
TODO test these modules and classes:
|
||||
autocomplete_w.AutoCompleteWindow
|
||||
debugger.Debugger
|
||||
outwin.OutputWindow (indirectly being tested with grep test)
|
||||
pyshell.PyShellEditorWindow
|
||||
"""
|
||||
|
||||
import idlelib.pyshell # Set Windows DPI awareness before Tk().
|
||||
from importlib import import_module
|
||||
@@ -91,15 +89,6 @@ _calltip_window_spec = {
|
||||
"Force-open-calltip does not work here.\n"
|
||||
}
|
||||
|
||||
_module_browser_spec = {
|
||||
'file': 'browser',
|
||||
'kwds': {},
|
||||
'msg': "Inspect names of module, class(with superclass if "
|
||||
"applicable), methods and functions.\nToggle nested items.\n"
|
||||
"Double clicking on items prints a traceback for an exception "
|
||||
"that is ignored."
|
||||
}
|
||||
|
||||
_color_delegator_spec = {
|
||||
'file': 'colorizer',
|
||||
'kwds': {},
|
||||
@@ -109,16 +98,6 @@ _color_delegator_spec = {
|
||||
"The default color scheme is in idlelib/config-highlight.def"
|
||||
}
|
||||
|
||||
CustomRun_spec = {
|
||||
'file': 'query',
|
||||
'kwds': {'title': 'Customize query.py Run',
|
||||
'_htest': True},
|
||||
'msg': "Enter with <Return> or [Run]. Print valid entry to Shell\n"
|
||||
"Arguments are parsed into a list\n"
|
||||
"Mode is currently restart True or False\n"
|
||||
"Close dialog with valid entry, <Escape>, [Cancel], [X]"
|
||||
}
|
||||
|
||||
ConfigDialog_spec = {
|
||||
'file': 'configdialog',
|
||||
'kwds': {'title': 'ConfigDialogTest',
|
||||
@@ -135,6 +114,24 @@ ConfigDialog_spec = {
|
||||
"changes made have persisted."
|
||||
}
|
||||
|
||||
CustomRun_spec = {
|
||||
'file': 'query',
|
||||
'kwds': {'title': 'Customize query.py Run',
|
||||
'_htest': True},
|
||||
'msg': "Enter with <Return> or [OK]. Print valid entry to Shell\n"
|
||||
"Arguments are parsed into a list\n"
|
||||
"Mode is currently restart True or False\n"
|
||||
"Close dialog with valid entry, <Escape>, [Cancel], [X]"
|
||||
}
|
||||
|
||||
_debug_object_browser_spec = {
|
||||
'file': 'debugobj',
|
||||
'kwds': {},
|
||||
'msg': "Double click on items up to the lowest level.\n"
|
||||
"Attributes of the objects and related information "
|
||||
"will be displayed side-by-side at each level."
|
||||
}
|
||||
|
||||
# TODO Improve message
|
||||
_dyn_option_menu_spec = {
|
||||
'file': 'dynoption',
|
||||
@@ -152,7 +149,7 @@ _editor_window_spec = {
|
||||
"Best to close editor first."
|
||||
}
|
||||
|
||||
GetKeysDialog_spec = {
|
||||
GetKeysWindow_spec = {
|
||||
'file': 'config_key',
|
||||
'kwds': {'title': 'Test keybindings',
|
||||
'action': 'find-again',
|
||||
@@ -173,8 +170,8 @@ _grep_dialog_spec = {
|
||||
'msg': "Click the 'Show GrepDialog' button.\n"
|
||||
"Test the various 'Find-in-files' functions.\n"
|
||||
"The results should be displayed in a new '*Output*' window.\n"
|
||||
"'Right-click'->'Go to file/line' anywhere in the search results "
|
||||
"should open that file \nin a new EditorWindow."
|
||||
"'Right-click'->'Go to file/line' in the search results\n "
|
||||
"should open that file in a new EditorWindow."
|
||||
}
|
||||
|
||||
HelpSource_spec = {
|
||||
@@ -190,7 +187,7 @@ HelpSource_spec = {
|
||||
"Any url ('www...', 'http...') is accepted.\n"
|
||||
"Test Browse with and without path, as cannot unittest.\n"
|
||||
"[Ok] or <Return> prints valid entry to shell\n"
|
||||
"[Cancel] or <Escape> prints None to shell"
|
||||
"<Escape>, [Cancel], or [X] prints None to shell"
|
||||
}
|
||||
|
||||
_io_binding_spec = {
|
||||
@@ -206,56 +203,36 @@ _io_binding_spec = {
|
||||
"Check that changes were saved by opening the file elsewhere."
|
||||
}
|
||||
|
||||
_linenumbers_drag_scrolling_spec = {
|
||||
'file': 'sidebar',
|
||||
'kwds': {},
|
||||
'msg': textwrap.dedent("""\
|
||||
1. Click on the line numbers and drag down below the edge of the
|
||||
window, moving the mouse a bit and then leaving it there for a while.
|
||||
The text and line numbers should gradually scroll down, with the
|
||||
selection updated continuously.
|
||||
|
||||
2. With the lines still selected, click on a line number above the
|
||||
selected lines. Only the line whose number was clicked should be
|
||||
selected.
|
||||
|
||||
3. Repeat step #1, dragging to above the window. The text and line
|
||||
numbers should gradually scroll up, with the selection updated
|
||||
continuously.
|
||||
|
||||
4. Repeat step #2, clicking a line number below the selection."""),
|
||||
}
|
||||
|
||||
_multi_call_spec = {
|
||||
'file': 'multicall',
|
||||
'kwds': {},
|
||||
'msg': "The following actions should trigger a print to console or IDLE"
|
||||
" Shell.\nEntering and leaving the text area, key entry, "
|
||||
"<Control-Key>,\n<Alt-Key-a>, <Control-Key-a>, "
|
||||
"<Alt-Control-Key-a>, \n<Control-Button-1>, <Alt-Button-1> and "
|
||||
"focusing out of the window\nare sequences to be tested."
|
||||
'msg': "The following should trigger a print to console or IDLE Shell.\n"
|
||||
"Entering and leaving the text area, key entry, <Control-Key>,\n"
|
||||
"<Alt-Key-a>, <Control-Key-a>, <Alt-Control-Key-a>, \n"
|
||||
"<Control-Button-1>, <Alt-Button-1> and focusing elsewhere."
|
||||
}
|
||||
|
||||
_module_browser_spec = {
|
||||
'file': 'browser',
|
||||
'kwds': {},
|
||||
'msg': textwrap.dedent("""
|
||||
"Inspect names of module, class(with superclass if applicable),
|
||||
"methods and functions. Toggle nested items. Double clicking
|
||||
"on items prints a traceback for an exception that is ignored.""")
|
||||
}
|
||||
|
||||
_multistatus_bar_spec = {
|
||||
'file': 'statusbar',
|
||||
'kwds': {},
|
||||
'msg': "Ensure presence of multi-status bar below text area.\n"
|
||||
"Click 'Update Status' to change the multi-status text"
|
||||
"Click 'Update Status' to change the status text"
|
||||
}
|
||||
|
||||
_object_browser_spec = {
|
||||
'file': 'debugobj',
|
||||
'kwds': {},
|
||||
'msg': "Double click on items up to the lowest level.\n"
|
||||
"Attributes of the objects and related information "
|
||||
"will be displayed side-by-side at each level."
|
||||
}
|
||||
|
||||
_path_browser_spec = {
|
||||
PathBrowser_spec = {
|
||||
'file': 'pathbrowser',
|
||||
'kwds': {},
|
||||
'kwds': {'_htest': True},
|
||||
'msg': "Test for correct display of all paths in sys.path.\n"
|
||||
"Toggle nested items up to the lowest level.\n"
|
||||
"Toggle nested items out to the lowest level.\n"
|
||||
"Double clicking on an item prints a traceback\n"
|
||||
"for an exception that is ignored."
|
||||
}
|
||||
@@ -291,6 +268,15 @@ _replace_dialog_spec = {
|
||||
"Click [Close] or [X] to close the 'Replace Dialog'."
|
||||
}
|
||||
|
||||
_scrolled_list_spec = {
|
||||
'file': 'scrolledlist',
|
||||
'kwds': {},
|
||||
'msg': "You should see a scrollable list of items\n"
|
||||
"Selecting (clicking) or double clicking an item "
|
||||
"prints the name to the console or Idle shell.\n"
|
||||
"Right clicking an item will display a popup."
|
||||
}
|
||||
|
||||
_search_dialog_spec = {
|
||||
'file': 'search',
|
||||
'kwds': {},
|
||||
@@ -306,15 +292,6 @@ _searchbase_spec = {
|
||||
"Its only action is to close."
|
||||
}
|
||||
|
||||
_scrolled_list_spec = {
|
||||
'file': 'scrolledlist',
|
||||
'kwds': {},
|
||||
'msg': "You should see a scrollable list of items\n"
|
||||
"Selecting (clicking) or double clicking an item "
|
||||
"prints the name to the console or Idle shell.\n"
|
||||
"Right clicking an item will display a popup."
|
||||
}
|
||||
|
||||
show_idlehelp_spec = {
|
||||
'file': 'help',
|
||||
'kwds': {},
|
||||
@@ -322,12 +299,31 @@ show_idlehelp_spec = {
|
||||
"Text is selectable. Window is scrollable."
|
||||
}
|
||||
|
||||
_stack_viewer_spec = {
|
||||
_sidebar_number_scrolling_spec = {
|
||||
'file': 'sidebar',
|
||||
'kwds': {},
|
||||
'msg': textwrap.dedent("""\
|
||||
1. Click on the line numbers and drag down below the edge of the
|
||||
window, moving the mouse a bit and then leaving it there for a
|
||||
while. The text and line numbers should gradually scroll down,
|
||||
with the selection updated continuously.
|
||||
|
||||
2. With the lines still selected, click on a line number above
|
||||
or below the selected lines. Only the line whose number was
|
||||
clicked should be selected.
|
||||
|
||||
3. Repeat step #1, dragging to above the window. The text and
|
||||
line numbers should gradually scroll up, with the selection
|
||||
updated continuously.
|
||||
|
||||
4. Repeat step #2, clicking a line number below the selection."""),
|
||||
}
|
||||
|
||||
_stackbrowser_spec = {
|
||||
'file': 'stackviewer',
|
||||
'kwds': {},
|
||||
'msg': "A stacktrace for a NameError exception.\n"
|
||||
"Expand 'idlelib ...' and '<locals>'.\n"
|
||||
"Check that exc_value, exc_tb, and exc_type are correct.\n"
|
||||
"Should have NameError and 1 traceback line."
|
||||
}
|
||||
|
||||
_tooltip_spec = {
|
||||
@@ -370,11 +366,12 @@ _widget_redirector_spec = {
|
||||
}
|
||||
|
||||
def run(*tests):
|
||||
"Run callables in tests."
|
||||
root = tk.Tk()
|
||||
root.title('IDLE htest')
|
||||
root.resizable(0, 0)
|
||||
|
||||
# a scrollable Label like constant width text widget.
|
||||
# A scrollable Label-like constant width text widget.
|
||||
frameLabel = tk.Frame(root, padx=10)
|
||||
frameLabel.pack()
|
||||
text = tk.Text(frameLabel, wrap='word')
|
||||
@@ -384,45 +381,44 @@ def run(*tests):
|
||||
scrollbar.pack(side='right', fill='y', expand=False)
|
||||
text.pack(side='left', fill='both', expand=True)
|
||||
|
||||
test_list = [] # List of tuples of the form (spec, callable widget)
|
||||
test_list = [] # Make list of (spec, callable) tuples.
|
||||
if tests:
|
||||
for test in tests:
|
||||
test_spec = globals()[test.__name__ + '_spec']
|
||||
test_spec['name'] = test.__name__
|
||||
test_list.append((test_spec, test))
|
||||
else:
|
||||
for k, d in globals().items():
|
||||
if k.endswith('_spec'):
|
||||
test_name = k[:-5]
|
||||
test_spec = d
|
||||
for key, dic in globals().items():
|
||||
if key.endswith('_spec'):
|
||||
test_name = key[:-5]
|
||||
test_spec = dic
|
||||
test_spec['name'] = test_name
|
||||
mod = import_module('idlelib.' + test_spec['file'])
|
||||
test = getattr(mod, test_name)
|
||||
test_list.append((test_spec, test))
|
||||
test_list.reverse() # So can pop in proper order in next_test.
|
||||
|
||||
test_name = tk.StringVar(root)
|
||||
callable_object = None
|
||||
test_kwds = None
|
||||
|
||||
def next_test():
|
||||
|
||||
nonlocal test_name, callable_object, test_kwds
|
||||
if len(test_list) == 1:
|
||||
next_button.pack_forget()
|
||||
test_spec, callable_object = test_list.pop()
|
||||
test_kwds = test_spec['kwds']
|
||||
test_kwds['parent'] = root
|
||||
test_name.set('Test ' + test_spec['name'])
|
||||
|
||||
text.configure(state='normal') # enable text editing
|
||||
text.delete('1.0','end')
|
||||
text.insert("1.0",test_spec['msg'])
|
||||
text.configure(state='disabled') # preserve read-only property
|
||||
text['state'] = 'normal' # Enable text replacement.
|
||||
text.delete('1.0', 'end')
|
||||
text.insert("1.0", test_spec['msg'])
|
||||
text['state'] = 'disabled' # Restore read-only property.
|
||||
|
||||
def run_test(_=None):
|
||||
widget = callable_object(**test_kwds)
|
||||
widget = callable_object(root, **test_kwds)
|
||||
try:
|
||||
print(widget.result)
|
||||
print(widget.result) # Only true for query classes(?).
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@@ -441,5 +437,6 @@ def run(*tests):
|
||||
next_test()
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
Reference in New Issue
Block a user