summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTerry Jan Reedy <tjreedy@udel.edu>2014-10-17 05:31:35 (GMT)
committerTerry Jan Reedy <tjreedy@udel.edu>2014-10-17 05:31:35 (GMT)
commitcd567365c9f95cf005d6bb7c1da7946b68a43ab4 (patch)
treef26214676f8957a3e89451cc4cb54239bd5ab113
parent9a6f8e18662c67cd41bf54ef3b8dbf2b7f5a3aeb (diff)
downloadcpython-cd567365c9f95cf005d6bb7c1da7946b68a43ab4.zip
cpython-cd567365c9f95cf005d6bb7c1da7946b68a43ab4.tar.gz
cpython-cd567365c9f95cf005d6bb7c1da7946b68a43ab4.tar.bz2
Issue #22629: Revise idle_test.htest, mostly docstring. Start revision of
htests to add # htest # marker for coveragepy and stop tcl errors.
-rw-r--r--Lib/idlelib/CallTipWindow.py52
-rw-r--r--Lib/idlelib/ClassBrowser.py13
-rw-r--r--Lib/idlelib/ColorDelegator.py22
-rw-r--r--Lib/idlelib/EditorWindow.py6
-rw-r--r--Lib/idlelib/GrepDialog.py2
-rw-r--r--Lib/idlelib/configDialog.py4
-rw-r--r--Lib/idlelib/dynOptionMenuWidget.py30
-rw-r--r--Lib/idlelib/idle_test/htest.py65
8 files changed, 112 insertions, 82 deletions
diff --git a/Lib/idlelib/CallTipWindow.py b/Lib/idlelib/CallTipWindow.py
index 84d22fd..170d146 100644
--- a/Lib/idlelib/CallTipWindow.py
+++ b/Lib/idlelib/CallTipWindow.py
@@ -133,37 +133,27 @@ class CallTip:
def _calltip_window(parent): # htest #
- import re
- from tkinter import Tk, Text, LEFT, BOTH
-
- root = Tk()
- root.title("Test calltips")
- width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
-
- class MyEditWin: # conceptually an editor_window
- def __init__(self):
- text = self.text = Text(root)
- text.pack(side=LEFT, fill=BOTH, expand=1)
- text.insert("insert", "string.split")
- root.update()
- self.calltip = CallTip(text)
-
- text.event_add("<<calltip-show>>", "(")
- text.event_add("<<calltip-hide>>", ")")
- text.bind("<<calltip-show>>", self.calltip_show)
- text.bind("<<calltip-hide>>", self.calltip_hide)
-
- text.focus_set()
- root.mainloop()
-
- def calltip_show(self, event):
- self.calltip.showtip("Hello world", "insert", "end")
-
- def calltip_hide(self, event):
- self.calltip.hidetip()
-
- MyEditWin()
+ from tkinter import Toplevel, Text, LEFT, BOTH
+
+ top = Toplevel(parent)
+ top.title("Test calltips")
+ top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
+ parent.winfo_rooty() + 150))
+ text = Text(top)
+ text.pack(side=LEFT, fill=BOTH, expand=1)
+ text.insert("insert", "string.split")
+ top.update()
+ calltip = CallTip(text)
+
+ def calltip_show(event):
+ calltip.showtip("(s=Hello world)", "insert", "end")
+ def calltip_hide(event):
+ calltip.hidetip()
+ text.event_add("<<calltip-show>>", "(")
+ text.event_add("<<calltip-hide>>", ")")
+ text.bind("<<calltip-show>>", calltip_show)
+ text.bind("<<calltip-hide>>", calltip_hide)
+ text.focus_set()
if __name__=='__main__':
from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/ClassBrowser.py b/Lib/idlelib/ClassBrowser.py
index a0e782e..5be65ef 100644
--- a/Lib/idlelib/ClassBrowser.py
+++ b/Lib/idlelib/ClassBrowser.py
@@ -19,6 +19,9 @@ from idlelib.WindowList import ListedToplevel
from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas
from idlelib.configHandler import idleConf
+file_open = None # Method...Item and Class...Item use this.
+# Normally PyShell.flist.open, but there is no PyShell.flist for htest.
+
class ClassBrowser:
def __init__(self, flist, name, path, _htest=False):
@@ -27,6 +30,9 @@ class ClassBrowser:
"""
_htest - bool, change box when location running htest.
"""
+ global file_open
+ if not _htest:
+ file_open = PyShell.flist.open
self.name = name
self.file = os.path.join(path[0], self.name + ".py")
self._htest = _htest
@@ -170,7 +176,7 @@ class ClassBrowserTreeItem(TreeItem):
def OnDoubleClick(self):
if not os.path.exists(self.file):
return
- edit = PyShell.flist.open(self.file)
+ edit = file_open(self.file)
if hasattr(self.cl, 'lineno'):
lineno = self.cl.lineno
edit.gotoline(lineno)
@@ -206,7 +212,7 @@ class MethodBrowserTreeItem(TreeItem):
def OnDoubleClick(self):
if not os.path.exists(self.file):
return
- edit = PyShell.flist.open(self.file)
+ edit = file_open(self.file)
edit.gotoline(self.cl.methods[self.name])
def _class_browser(parent): #Wrapper for htest
@@ -221,8 +227,9 @@ def _class_browser(parent): #Wrapper for htest
dir, file = os.path.split(file)
name = os.path.splitext(file)[0]
flist = PyShell.PyShellFileList(parent)
+ global file_open
+ file_open = flist.open
ClassBrowser(flist, name, [dir], _htest=True)
- parent.mainloop()
if __name__ == "__main__":
from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/ColorDelegator.py b/Lib/idlelib/ColorDelegator.py
index 22bb22f..13a9010 100644
--- a/Lib/idlelib/ColorDelegator.py
+++ b/Lib/idlelib/ColorDelegator.py
@@ -2,7 +2,6 @@ import time
import re
import keyword
import builtins
-from tkinter import *
from idlelib.Delegator import Delegator
from idlelib.configHandler import idleConf
@@ -234,20 +233,23 @@ class ColorDelegator(Delegator):
for tag in self.tagdefs:
self.tag_remove(tag, "1.0", "end")
-def _color_delegator(parent):
+def _color_delegator(parent): # htest #
+ from tkinter import Toplevel, Text
from idlelib.Percolator import Percolator
- root = Tk()
- root.title("Test ColorDelegator")
- width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- source = "if somename: x = 'abc' # comment\nprint"
- text = Text(root, background="white")
- text.insert("insert", source)
+
+ top = Toplevel(parent)
+ top.title("Test ColorDelegator")
+ top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
+ parent.winfo_rooty() + 150))
+ source = "if somename: x = 'abc' # comment\nprint\n"
+ text = Text(top, background="white")
text.pack(expand=1, fill="both")
+ text.insert("insert", source)
+ text.focus_set()
+
p = Percolator(text)
d = ColorDelegator()
p.insertfilter(d)
- root.mainloop()
if __name__ == "__main__":
from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index 1056552..bdf4a1a 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -1711,7 +1711,8 @@ def fixwordbreaks(root):
tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]')
-def _editor_window(parent):
+def _editor_window(parent): # htest #
+ # error if close master window first - timer event, after script
root = parent
fixwordbreaks(root)
if sys.argv[1:]:
@@ -1721,7 +1722,8 @@ def _editor_window(parent):
macosxSupport.setupApp(root, None)
edit = EditorWindow(root=root, filename=filename)
edit.text.bind("<<close-all-windows>>", edit.close_event)
- parent.mainloop()
+ # Does not stop error, neither does following
+ # edit.text.bind("<<close-window>>", edit.close_event)
if __name__ == '__main__':
from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/GrepDialog.py b/Lib/idlelib/GrepDialog.py
index 5d22a9e..aa866d0 100644
--- a/Lib/idlelib/GrepDialog.py
+++ b/Lib/idlelib/GrepDialog.py
@@ -131,7 +131,7 @@ class GrepDialog(SearchDialogBase):
self.top.withdraw()
-def _grep_dialog(parent): # for htest
+def _grep_dialog(parent): # htest #
from idlelib.PyShell import PyShellFileList
root = Tk()
root.title("Test GrepDialog")
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
index cd3d5c0..938b0bc 100644
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -24,7 +24,7 @@ from idlelib import macosxSupport
class ConfigDialog(Toplevel):
- def __init__(self, parent, title, _htest=False, _utest=False):
+ def __init__(self, parent, title='', _htest=False, _utest=False):
"""
_htest - bool, change box location when running htest
_utest - bool, don't wait_window when running unittest
@@ -36,7 +36,7 @@ class ConfigDialog(Toplevel):
self.wm_withdraw()
self.configure(borderwidth=5)
- self.title('IDLE Preferences')
+ self.title(title or 'IDLE Preferences')
self.geometry(
"+%d+%d" % (parent.winfo_rootx() + 20,
parent.winfo_rooty() + (30 if not _htest else 150)))
diff --git a/Lib/idlelib/dynOptionMenuWidget.py b/Lib/idlelib/dynOptionMenuWidget.py
index 877ca1b..515b4ba 100644
--- a/Lib/idlelib/dynOptionMenuWidget.py
+++ b/Lib/idlelib/dynOptionMenuWidget.py
@@ -2,17 +2,15 @@
OptionMenu widget modified to allow dynamic menu reconfiguration
and setting of highlightthickness
"""
-from tkinter import OptionMenu, _setit, Tk, StringVar, Button
-
import copy
-import re
+from tkinter import OptionMenu, _setit, StringVar, Button
class DynOptionMenu(OptionMenu):
"""
unlike OptionMenu, our kwargs can include highlightthickness
"""
def __init__(self, master, variable, value, *values, **kwargs):
- #get a copy of kwargs before OptionMenu.__init__ munges them
+ # TODO copy value instead of whole dict
kwargsCopy=copy.copy(kwargs)
if 'highlightthickness' in list(kwargs.keys()):
del(kwargs['highlightthickness'])
@@ -35,22 +33,24 @@ class DynOptionMenu(OptionMenu):
if value:
self.variable.set(value)
-def _dyn_option_menu(parent):
- root = Tk()
- root.title("Tets dynamic option menu")
- var = StringVar(root)
- width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
+def _dyn_option_menu(parent): # htest #
+ from tkinter import Toplevel
+
+ top = Toplevel()
+ top.title("Tets dynamic option menu")
+ top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
+ parent.winfo_rooty() + 150))
+ top.focus_set()
+
+ var = StringVar(top)
var.set("Old option set") #Set the default value
- dyn = DynOptionMenu(root,var, "old1","old2","old3","old4")
+ dyn = DynOptionMenu(top,var, "old1","old2","old3","old4")
dyn.pack()
def update():
- dyn.SetMenu(["new1","new2","new3","new4"],value="new option set")
-
- button = Button(root, text="Change option set", command=update)
+ dyn.SetMenu(["new1","new2","new3","new4"], value="new option set")
+ button = Button(top, text="Change option set", command=update)
button.pack()
- root.mainloop()
if __name__ == '__main__':
from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py
index d0faf44..d673fe4 100644
--- a/Lib/idlelib/idle_test/htest.py
+++ b/Lib/idlelib/idle_test/htest.py
@@ -1,11 +1,24 @@
'''Run human tests of Idle's window, dialog, and popup widgets.
run(*tests)
-Run each callable in tests after finding the matching test spec in this file.
-If there are none, run an htest for each spec dict in this file after finding
-the matching callable in the module named in the spec.
+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.
+
+In a tested module, let X be a global name bound to a callable (class
+or function) whose .__name__ attrubute 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 corresonding 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 widget callable.
End the module with
if __name__ == '__main__':
@@ -13,13 +26,25 @@ if __name__ == '__main__':
from idlelib.idle_test.htest import run
run(X)
-The X object must have a .__name__ attribute and a 'parent' parameter.
-X will often be a widget class, but a callable instance with .__name__
-or a wrapper function also work. The name of wrapper functions, like
-'_editor_window', should start with '_'.
+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.
+
+[report]
+exclude_lines =
+ .*# htest #
+ if __name__ == .__main__.:
-This file must contain a matching instance of the following template,
-with X.__name__ prepended, as in '_editor_window_spec ...'.
+(The "." instead of "'" is intentional and necessary.)
+
+
+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 = {
'file': '',
@@ -27,18 +52,19 @@ _spec = {
'msg': ""
}
-file (no .py): used in run() to import the file and get X.
-kwds: passed to X (**kwds), after 'parent' is added, to initialize X.
-title: an example; used for some widgets, delete if not.
-msg: displayed in a master window. Hints as to how the user might
- test the widget. Close the window to skip or end the test.
+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.
+msg: master window hints about testing the widget.
-Modules not being tested at the moment:
+
+Modules and classes not being tested at the moment:
PyShell.PyShellEditorWindow
Debugger.Debugger
AutoCompleteWindow.AutoCompleteWindow
OutputWindow.OutputWindow (indirectly being tested with grep test)
'''
+
from importlib import import_module
from idlelib.macosxSupport import _initializeTkVariantTests
import tkinter as tk
@@ -79,7 +105,7 @@ _color_delegator_spec = {
ConfigDialog_spec = {
'file': 'configDialog',
- 'kwds': {'title': 'Settings',
+ 'kwds': {'title': 'ConfigDialogTest',
'_htest': True,},
'msg': "IDLE preferences dialog.\n"
"In the 'Fonts/Tabs' tab, changing font face, should update the "
@@ -92,6 +118,7 @@ ConfigDialog_spec = {
"changes made have persisted."
}
+# TODO Improve message
_dyn_option_menu_spec = {
'file': 'dynOptionMenuWidget',
'kwds': {},
@@ -100,10 +127,12 @@ _dyn_option_menu_spec = {
"Select one of the many options in the 'new option set'."
}
+# TODO edit wrapper
_editor_window_spec = {
'file': 'EditorWindow',
'kwds': {},
- 'msg': "Test editor functions of interest."
+ 'msg': "Test editor functions of interest.\n"
+ "Best to close editor first."
}
GetCfgSectionNameDialog_spec = {