bpo-33855: Minimally test all IDLE modules. (GH-7689)

Create a template for minimally testing a tkinter-using module by importing it and instantiating its class(es).  Add a test file for all non-startup IDLE modules.  Edit existing files and update coverage.  This is part 1 of 3, covering the 21 autocomplete to help modules and touching 33 idlelib files.
This commit is contained in:
Terry Jan Reedy
2018-06-15 18:20:55 -04:00
committed by GitHub
parent 6c5a4b3156
commit ee5ef309c7
34 changed files with 422 additions and 108 deletions

View File

@@ -226,7 +226,6 @@ class AutoComplete:
AutoComplete.reload()
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_autocomplete', verbosity=2)

View File

@@ -458,3 +458,10 @@ class AutoCompleteWindow:
self.listbox = None
self.autocompletewindow.destroy()
self.autocompletewindow = None
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_autocomplete_w', verbosity=2, exit=False)
# TODO: autocomplete/w htest here

View File

@@ -159,6 +159,9 @@ def _calltip_window(parent): # htest #
text.bind("<<calltip-hide>>", calltip_hide)
text.focus_set()
if __name__=='__main__':
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_calltips', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_calltip_window)

View File

@@ -286,9 +286,8 @@ def _color_delegator(parent): # htest #
p.insertfilter(d)
if __name__ == "__main__":
import unittest
unittest.main('idlelib.idle_test.test_colorizer',
verbosity=2, exit=False)
from unittest import main
main('idlelib.idle_test.test_colorizer', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_color_delegator)

View File

@@ -12,7 +12,7 @@ from idlelib.windows import ListedToplevel
class Idb(bdb.Bdb):
def __init__(self, gui):
self.gui = gui
self.gui = gui # An instance of Debugger or proxy of remote.
bdb.Bdb.__init__(self)
def user_line(self, frame):
@@ -63,7 +63,7 @@ class Debugger:
if idb is None:
idb = Idb(self)
self.pyshell = pyshell
self.idb = idb
self.idb = idb # If passed, a proxy of remote instance.
self.frame = None
self.make_gui()
self.interacting = 0
@@ -542,3 +542,9 @@ class NamespaceViewer:
def close(self):
self.frame.destroy()
if __name__ == "__main__":
from unittest import main
main('idlelib.idle_test.test_debugger', verbosity=2, exit=False)
# TODO: htest?

View File

@@ -386,3 +386,8 @@ def restart_subprocess_debugger(rpcclt):
idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\
(gui_adap_oid,), {})
assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid'
if __name__ == "__main__":
from unittest import main
main('idlelib.idle_test.test_debugger', verbosity=2, exit=False)

View File

@@ -71,7 +71,7 @@ class ClassTreeItem(ObjectTreeItem):
class AtomicObjectTreeItem(ObjectTreeItem):
def IsExpandable(self):
return 0
return False
class SequenceTreeItem(ObjectTreeItem):
def IsExpandable(self):
@@ -135,5 +135,8 @@ def _object_browser(parent): # htest #
node.update()
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_object_browser)

View File

@@ -34,3 +34,8 @@ class StubObjectTreeItem:
def _GetSubList(self):
sub_list = self.sockio.remotecall(self.oid, "_GetSubList", (), {})
return [StubObjectTreeItem(self.sockio, oid) for oid in sub_list]
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_debugobj_r', verbosity=2)

View File

@@ -1706,8 +1706,8 @@ def _editor_window(parent): # htest #
# edit.text.bind("<<close-window>>", edit.close_event)
if __name__ == '__main__':
import unittest
unittest.main('idlelib.idle_test.test_editor', verbosity=2, exit=False)
from unittest import main
main('idlelib.idle_test.test_editor', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_editor_window)

View File

@@ -1,7 +1,7 @@
import os
"idlelib.filelist"
from tkinter import *
import tkinter.messagebox as tkMessageBox
import os
from tkinter import messagebox as tkMessageBox
class FileList:
@@ -111,7 +111,8 @@ class FileList:
return os.path.normpath(filename)
def _test():
def _test(): # TODO check and convert to htest
from tkinter import Tk
from idlelib.editor import fixwordbreaks
from idlelib.run import fix_scaling
import sys
@@ -120,13 +121,12 @@ def _test():
fixwordbreaks(root)
root.withdraw()
flist = FileList(root)
if sys.argv[1:]:
for filename in sys.argv[1:]:
flist.open(filename)
else:
flist.new()
flist.new()
if flist.inversedict:
root.mainloop()
if __name__ == '__main__':
_test()
from unittest import main
main('idlelib.idle_test.test_filelist', verbosity=2)
# _test()

View File

@@ -193,8 +193,8 @@ def _grep_dialog(parent): # htest #
button.pack()
if __name__ == "__main__":
import unittest
unittest.main('idlelib.idle_test.test_grep', verbosity=2, exit=False)
from unittest import main
main('idlelib.idle_test.test_grep', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_grep_dialog)

View File

@@ -271,5 +271,8 @@ def show_idlehelp(parent):
HelpWindow(parent, filename, 'IDLE Help (%s)' % python_version())
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_help', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(show_idlehelp)

View File

@@ -0,0 +1,30 @@
"Test , coverage %."
from idlelib import
import unittest
from test.support import requires
from tkinter import Tk
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
requires('gui')
cls.root = Tk()
cls.root.withdraw()
@classmethod
def tearDownClass(cls):
cls.root.update_idletasks()
## for id in cls.root.tk.call('after', 'info'):
## cls.root.after_cancel(id) # Need for EditorWindow.
cls.root.destroy()
del cls.root
def test_init(self):
self.assert
if __name__ == '__main__':
unittest.main(verbosity=2)

View File

@@ -1,7 +1,5 @@
''' Test autocomplete and autocomple_w
"Test autocomplete, coverage 57%."
Coverage of autocomple: 56%
'''
import unittest
from test.support import requires
from tkinter import Tk, Text
@@ -11,9 +9,6 @@ import idlelib.autocomplete_w as acw
from idlelib.idle_test.mock_idle import Func
from idlelib.idle_test.mock_tk import Event
class AutoCompleteWindow:
def complete():
return
class DummyEditwin:
def __init__(self, root, text):

View File

@@ -0,0 +1,32 @@
"Test autocomplete_w, coverage 11%."
import unittest
from test.support import requires
from tkinter import Tk, Text
import idlelib.autocomplete_w as acw
class AutoCompleteWindowTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
requires('gui')
cls.root = Tk()
cls.root.withdraw()
cls.text = Text(cls.root)
cls.acw = acw.AutoCompleteWindow(cls.text)
@classmethod
def tearDownClass(cls):
del cls.text, cls.acw
cls.root.update_idletasks()
cls.root.destroy()
del cls.root
def test_init(self):
self.assertEqual(self.acw.widget, self.text)
if __name__ == '__main__':
unittest.main(verbosity=2)

View File

@@ -1,9 +1,9 @@
"""Unit tests for idlelib.autoexpand"""
"Test autoexpand, coverage 100%."
from idlelib.autoexpand import AutoExpand
import unittest
from test.support import requires
from tkinter import Text, Tk
#from idlelib.idle_test.mock_tk import Text
from idlelib.autoexpand import AutoExpand
class Dummy_Editwin:
@@ -15,15 +15,27 @@ class AutoExpandTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
if 'tkinter' in str(Text):
requires('gui')
cls.tk = Tk()
cls.text = Text(cls.tk)
else:
cls.text = Text()
requires('gui')
cls.tk = Tk()
cls.text = Text(cls.tk)
cls.auto_expand = AutoExpand(Dummy_Editwin(cls.text))
cls.auto_expand.bell = lambda: None
# If mock_tk.Text._decode understood indexes 'insert' with suffixed 'linestart',
# 'wordstart', and 'lineend', used by autoexpand, we could use the following
# to run these test on non-gui machines (but check bell).
## try:
## requires('gui')
## #raise ResourceDenied() # Uncomment to test mock.
## except ResourceDenied:
## from idlelib.idle_test.mock_tk import Text
## cls.text = Text()
## cls.text.bell = lambda: None
## else:
## from tkinter import Tk, Text
## cls.tk = Tk()
## cls.text = Text(cls.tk)
@classmethod
def tearDownClass(cls):
del cls.text, cls.auto_expand

View File

@@ -1,20 +1,16 @@
""" Test idlelib.browser.
"Test browser, coverage 90%."
Coverage: 88%
(Higher, because should exclude 3 lines that .coveragerc won't exclude.)
"""
from idlelib import browser
from test.support import requires
import unittest
from unittest import mock
from idlelib.idle_test.mock_idle import Func
from collections import deque
import os.path
import pyclbr
from tkinter import Tk
from test.support import requires
import unittest
from unittest import mock
from idlelib.idle_test.mock_idle import Func
from idlelib import browser
from idlelib import filelist
from idlelib.tree import TreeNode

View File

@@ -0,0 +1,29 @@
"Test calltip_w, coverage 18%."
from idlelib import calltip_w
import unittest
from test.support import requires
from tkinter import Tk, Text
class CallTipTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
requires('gui')
cls.root = Tk()
cls.root.withdraw()
cls.text = Text(cls.root)
cls.calltip = calltip_w.CallTip(cls.text)
@classmethod
def tearDownClass(cls):
cls.root.update_idletasks()
cls.root.destroy()
del cls.text, cls.root
def test_init(self):
self.assertEqual(self.calltip.widget, self.text)
if __name__ == '__main__':
unittest.main(verbosity=2)

View File

@@ -1,9 +1,12 @@
"Test calltips, coverage 60%"
from idlelib import calltips
import unittest
import idlelib.calltips as ct
import textwrap
import types
default_tip = ct._default_callable_argspec
default_tip = calltips._default_callable_argspec
# Test Class TC is used in multiple get_argspec test methods
class TC():
@@ -31,9 +34,11 @@ class TC():
@staticmethod
def sm(b): 'doc'
tc = TC()
signature = ct.get_argspec # 2.7 and 3.x use different functions
tc = TC()
signature = calltips.get_argspec # 2.7 and 3.x use different functions
class Get_signatureTest(unittest.TestCase):
# The signature function must return a string, even if blank.
# Test a variety of objects to be sure that none cause it to raise
@@ -54,14 +59,18 @@ class Get_signatureTest(unittest.TestCase):
self.assertEqual(signature(obj), out)
if List.__doc__ is not None:
gtest(List, '(iterable=(), /)' + ct._argument_positional + '\n' +
List.__doc__)
gtest(List, '(iterable=(), /)' + calltips._argument_positional
+ '\n' + List.__doc__)
gtest(list.__new__,
'(*args, **kwargs)\nCreate and return a new object. See help(type) for accurate signature.')
'(*args, **kwargs)\n'
'Create and return a new object. '
'See help(type) for accurate signature.')
gtest(list.__init__,
'(self, /, *args, **kwargs)' + ct._argument_positional + '\n' +
'Initialize self. See help(type(self)) for accurate signature.')
append_doc = ct._argument_positional + "\nAppend object to the end of the list."
'(self, /, *args, **kwargs)'
+ calltips._argument_positional + '\n' +
'Initialize self. See help(type(self)) for accurate signature.')
append_doc = (calltips._argument_positional
+ "\nAppend object to the end of the list.")
gtest(list.append, '(self, object, /)' + append_doc)
gtest(List.append, '(self, object, /)' + append_doc)
gtest([].append, '(object, /)' + append_doc)
@@ -70,12 +79,17 @@ class Get_signatureTest(unittest.TestCase):
gtest(SB(), default_tip)
import re
p = re.compile('')
gtest(re.sub, '''(pattern, repl, string, count=0, flags=0)\nReturn the string obtained by replacing the leftmost
gtest(re.sub, '''\
(pattern, repl, string, count=0, flags=0)
Return the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in string by the
replacement repl. repl can be either a string or a callable;
if a string, backslash escapes in it are processed. If it is
a callable, it's passed the Match object and must return''')
gtest(p.sub, '''(repl, string, count=0)\nReturn the string obtained by replacing the leftmost non-overlapping occurrences o...''')
gtest(p.sub, '''\
(repl, string, count=0)
Return the string obtained by replacing the leftmost \
non-overlapping occurrences o...''')
def test_signature_wrap(self):
if textwrap.TextWrapper.__doc__ is not None:
@@ -88,7 +102,7 @@ a callable, it's passed the Match object and must return''')
def test_docline_truncation(self):
def f(): pass
f.__doc__ = 'a'*300
self.assertEqual(signature(f), '()\n' + 'a' * (ct._MAX_COLS-3) + '...')
self.assertEqual(signature(f), '()\n' + 'a' * (calltips._MAX_COLS-3) + '...')
def test_multiline_docstring(self):
# Test fewer lines than max.
@@ -107,7 +121,7 @@ bytes() -> empty bytes object''')
# Test more than max lines
def f(): pass
f.__doc__ = 'a\n' * 15
self.assertEqual(signature(f), '()' + '\na' * ct._MAX_LINES)
self.assertEqual(signature(f), '()' + '\na' * calltips._MAX_LINES)
def test_functions(self):
def t1(): 'doc'
@@ -135,8 +149,9 @@ bytes() -> empty bytes object''')
def test_bound_methods(self):
# test that first parameter is correctly removed from argspec
doc = '\ndoc' if TC.__doc__ is not None else ''
for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"), (tc.t6, "(self)"),
(tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),):
for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"),
(tc.t6, "(self)"), (tc.__call__, '(ci)'),
(tc, '(ci)'), (TC.cm, "(a)"),):
self.assertEqual(signature(meth), mtip + doc)
def test_starred_parameter(self):
@@ -153,7 +168,7 @@ bytes() -> empty bytes object''')
class Test:
def __call__(*, a): pass
mtip = ct._invalid_method
mtip = calltips._invalid_method
self.assertEqual(signature(C().m2), mtip)
self.assertEqual(signature(Test()), mtip)
@@ -161,7 +176,7 @@ bytes() -> empty bytes object''')
# test that re works to delete a first parameter name that
# includes non-ascii chars, such as various forms of A.
uni = "(A\u0391\u0410\u05d0\u0627\u0905\u1e00\u3042, a)"
assert ct._first_param.sub('', uni) == '(a)'
assert calltips._first_param.sub('', uni) == '(a)'
def test_no_docstring(self):
def nd(s):
@@ -194,9 +209,10 @@ bytes() -> empty bytes object''')
class Get_entityTest(unittest.TestCase):
def test_bad_entity(self):
self.assertIsNone(ct.get_entity('1/0'))
self.assertIsNone(calltips.get_entity('1/0'))
def test_good_entity(self):
self.assertIs(ct.get_entity('int'), int)
self.assertIs(calltips.get_entity('int'), int)
if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
unittest.main(verbosity=2)

View File

@@ -1,16 +1,12 @@
"""Test idlelib.codecontext.
Coverage: 100%
"""
import re
"Test codecontext, coverage 100%"
from idlelib import codecontext
import unittest
from unittest import mock
from test.support import requires
from tkinter import Tk, Frame, Text, TclError
import idlelib.codecontext as codecontext
import re
from idlelib import config

Some files were not shown because too many files have changed in this diff Show More