From 508568764593dca3844a51c10f1493413a51d66f Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Fri, 15 Jun 2018 15:38:35 -0700 Subject: [PATCH] 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. (cherry picked from commit ee5ef309c7e2daef1248730145408f700732c42e) Co-authored-by: Terry Jan Reedy --- Lib/idlelib/autocomplete.py | 1 - Lib/idlelib/autocomplete_w.py | 7 +++ Lib/idlelib/calltip_w.py | 5 +- Lib/idlelib/colorizer.py | 5 +- Lib/idlelib/debugger.py | 10 +++- Lib/idlelib/debugger_r.py | 5 ++ Lib/idlelib/debugobj.py | 5 +- Lib/idlelib/debugobj_r.py | 5 ++ Lib/idlelib/editor.py | 4 +- Lib/idlelib/filelist.py | 20 +++---- Lib/idlelib/grep.py | 4 +- Lib/idlelib/help.py | 3 + Lib/idlelib/idle_test/template.py | 30 ++++++++++ Lib/idlelib/idle_test/test_autocomplete.py | 7 +-- Lib/idlelib/idle_test/test_autocomplete_w.py | 32 ++++++++++ Lib/idlelib/idle_test/test_autoexpand.py | 30 +++++++--- Lib/idlelib/idle_test/test_browser.py | 16 ++--- Lib/idlelib/idle_test/test_calltip_w.py | 29 ++++++++++ Lib/idlelib/idle_test/test_calltips.py | 58 ++++++++++++------- Lib/idlelib/idle_test/test_codecontext.py | 10 +--- Lib/idlelib/idle_test/test_colorizer.py | 9 +-- Lib/idlelib/idle_test/test_config.py | 9 ++- Lib/idlelib/idle_test/test_config_key.py | 4 +- Lib/idlelib/idle_test/test_configdialog.py | 3 +- Lib/idlelib/idle_test/test_debugger.py | 8 +-- Lib/idlelib/idle_test/test_debugger_r.py | 29 ++++++++++ Lib/idlelib/idle_test/test_debugobj.py | 57 ++++++++++++++++++ Lib/idlelib/idle_test/test_debugobj_r.py | 22 +++++++ Lib/idlelib/idle_test/test_delegator.py | 6 +- Lib/idlelib/idle_test/test_editor.py | 42 ++++++++++++-- Lib/idlelib/idle_test/test_filelist.py | 33 +++++++++++ Lib/idlelib/idle_test/test_grep.py | 12 +++- Lib/idlelib/idle_test/test_help.py | 8 +-- .../2018-06-14-11-35-50.bpo-33855.XL230W.rst | 2 + 34 files changed, 422 insertions(+), 108 deletions(-) create mode 100644 Lib/idlelib/idle_test/template.py create mode 100644 Lib/idlelib/idle_test/test_autocomplete_w.py create mode 100644 Lib/idlelib/idle_test/test_calltip_w.py create mode 100644 Lib/idlelib/idle_test/test_debugger_r.py create mode 100644 Lib/idlelib/idle_test/test_debugobj.py create mode 100644 Lib/idlelib/idle_test/test_debugobj_r.py create mode 100644 Lib/idlelib/idle_test/test_filelist.py create mode 100644 Misc/NEWS.d/next/IDLE/2018-06-14-11-35-50.bpo-33855.XL230W.rst diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index edf445f08b5..9caf50d5d0c 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -226,7 +226,6 @@ class AutoComplete: AutoComplete.reload() - if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_autocomplete', verbosity=2) diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index 12113f95e63..66211d4554a 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -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 diff --git a/Lib/idlelib/calltip_w.py b/Lib/idlelib/calltip_w.py index bf967f40b6a..122b73abef6 100644 --- a/Lib/idlelib/calltip_w.py +++ b/Lib/idlelib/calltip_w.py @@ -159,6 +159,9 @@ def _calltip_window(parent): # htest # text.bind("<>", 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) diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index 1f31ce22d7e..d626d23121d 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -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) diff --git a/Lib/idlelib/debugger.py b/Lib/idlelib/debugger.py index 114d0d128e8..477b514180c 100644 --- a/Lib/idlelib/debugger.py +++ b/Lib/idlelib/debugger.py @@ -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? diff --git a/Lib/idlelib/debugger_r.py b/Lib/idlelib/debugger_r.py index bc971276de6..01a3bd25998 100644 --- a/Lib/idlelib/debugger_r.py +++ b/Lib/idlelib/debugger_r.py @@ -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) diff --git a/Lib/idlelib/debugobj.py b/Lib/idlelib/debugobj.py index b70b13cec48..5a4c9978842 100644 --- a/Lib/idlelib/debugobj.py +++ b/Lib/idlelib/debugobj.py @@ -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) diff --git a/Lib/idlelib/debugobj_r.py b/Lib/idlelib/debugobj_r.py index 8031aaeaf1f..75e75ebe5ac 100644 --- a/Lib/idlelib/debugobj_r.py +++ b/Lib/idlelib/debugobj_r.py @@ -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) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 7c3f215e9f9..0095bd03bb7 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1706,8 +1706,8 @@ def _editor_window(parent): # htest # # edit.text.bind("<>", 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) diff --git a/Lib/idlelib/filelist.py b/Lib/idlelib/filelist.py index 5e1a3dcd77d..52628392e61 100644 --- a/Lib/idlelib/filelist.py +++ b/Lib/idlelib/filelist.py @@ -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() diff --git a/Lib/idlelib/grep.py b/Lib/idlelib/grep.py index c55c48cf2d6..8cc293c380d 100644 --- a/Lib/idlelib/grep.py +++ b/Lib/idlelib/grep.py @@ -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) diff --git a/Lib/idlelib/help.py b/Lib/idlelib/help.py index fa6112a3394..21b5ea5a816 100644 --- a/Lib/idlelib/help.py +++ b/Lib/idlelib/help.py @@ -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) diff --git a/Lib/idlelib/idle_test/template.py b/Lib/idlelib/idle_test/template.py new file mode 100644 index 00000000000..34ceac3f405 --- /dev/null +++ b/Lib/idlelib/idle_test/template.py @@ -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) diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index f3f2dea4246..d7ee00af94b 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -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): diff --git a/Lib/idlelib/idle_test/test_autocomplete_w.py b/Lib/idlelib/idle_test/test_autocomplete_w.py new file mode 100644 index 00000000000..b1bdc6c7c6e --- /dev/null +++ b/Lib/idlelib/idle_test/test_autocomplete_w.py @@ -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) diff --git a/Lib/idlelib/idle_test/test_autoexpand.py b/Lib/idlelib/idle_test/test_autoexpand.py index ae8186cdc49..e5f44c46871 100644 --- a/Lib/idlelib/idle_test/test_autoexpand.py +++ b/Lib/idlelib/idle_test/test_autoexpand.py @@ -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 diff --git a/Lib/idlelib/idle_test/test_browser.py b/Lib/idlelib/idle_test/test_browser.py index 34eb332c1df..905dc1f47e3 100644 --- a/Lib/idlelib/idle_test/test_browser.py +++ b/Lib/idlelib/idle_test/test_browser.py @@ -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 diff --git a/Lib/idlelib/idle_test/test_calltip_w.py b/Lib/idlelib/idle_test/test_calltip_w.py new file mode 100644 index 00000000000..03f1e9a68a2 --- /dev/null +++ b/Lib/idlelib/idle_test/test_calltip_w.py @@ -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) diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py index a58229d36ed..2cf0e188dae 100644 --- a/Lib/idlelib/idle_test/test_calltips.py +++ b/Lib/idlelib/idle_test/test_calltips.py @@ -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) diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py index 2e59b8501c9..c349456d741 100644 --- a/Lib/idlelib/idle_test/test_codecontext.py +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -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 diff --git a/Lib/idlelib/idle_test/test_colorizer.py b/Lib/idlelib/idle_test/test_colorizer.py index 238bc3e1141..1e74bed1f0c 100644 --- a/Lib/idlelib/idle_test/test_colorizer.py +++ b/Lib/idlelib/idle_test/test_colorizer.py @@ -1,10 +1,6 @@ -'''Test idlelib/colorizer.py +"Test colorizer, coverage 25%." -Perform minimal sanity checks that module imports and some things run. - -Coverage 22%. -''' -from idlelib import colorizer # always test import +from idlelib import colorizer from test.support import requires from tkinter import Tk, Text import unittest @@ -36,6 +32,7 @@ class ColorConfigTest(unittest.TestCase): def test_colorizer(self): colorizer.color_config(self.text) + class ColorDelegatorTest(unittest.TestCase): @classmethod diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py index abfec7993e0..e6f553d4847 100644 --- a/Lib/idlelib/idle_test/test_config.py +++ b/Lib/idlelib/idle_test/test_config.py @@ -1,9 +1,9 @@ -'''Test idlelib.config. - -Coverage: 96% (100% for IdleConfParser, IdleUserConfParser*, ConfigChanges). +"""Test config, coverage 93%. +(100% for IdleConfParser, IdleUserConfParser*, ConfigChanges). * Exception is OSError clause in Save method. Much of IdleConf is also exercised by ConfigDialog and test_configdialog. -''' +""" +from idlelib import config import copy import sys import os @@ -12,7 +12,6 @@ from test.support import captured_stderr, findfile import unittest from unittest import mock import idlelib -from idlelib import config from idlelib.idle_test.mock_idle import Func # Tests should not depend on fortuitous user configurations. diff --git a/Lib/idlelib/idle_test/test_config_key.py b/Lib/idlelib/idle_test/test_config_key.py index 9074e23aab3..08471666a45 100644 --- a/Lib/idlelib/idle_test/test_config_key.py +++ b/Lib/idlelib/idle_test/test_config_key.py @@ -1,7 +1,5 @@ -''' Test idlelib.config_key. +"Test config_key, coverage 75%" -Coverage: 56% from creating and closing dialog. -''' from idlelib import config_key from test.support import requires import sys diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index 26aba32c47e..fe712b18a5e 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -1,7 +1,6 @@ -"""Test idlelib.configdialog. +"""Test configdialog, coverage 94%. Half the class creates dialog, half works with user customizations. -Coverage: 95%. """ from idlelib import configdialog from test.support import requires diff --git a/Lib/idlelib/idle_test/test_debugger.py b/Lib/idlelib/idle_test/test_debugger.py index bcba9a45c16..35efb3411c7 100644 --- a/Lib/idlelib/idle_test/test_debugger.py +++ b/Lib/idlelib/idle_test/test_debugger.py @@ -1,11 +1,9 @@ -''' Test idlelib.debugger. +"Test debugger, coverage 19%" -Coverage: 19% -''' from idlelib import debugger +import unittest from test.support import requires requires('gui') -import unittest from tkinter import Tk @@ -25,5 +23,7 @@ class NameSpaceTest(unittest.TestCase): debugger.NamespaceViewer(self.root, 'Test') +# Other classes are Idb, Debugger, and StackViewer. + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_debugger_r.py b/Lib/idlelib/idle_test/test_debugger_r.py new file mode 100644 index 00000000000..199f63447ce --- /dev/null +++ b/Lib/idlelib/idle_test/test_debugger_r.py @@ -0,0 +1,29 @@ +"Test debugger_r, coverage 30%." + +from idlelib import debugger_r +import unittest +from test.support import requires +from tkinter import Tk + + +class Test(unittest.TestCase): + +## @classmethod +## def setUpClass(cls): +## requires('gui') +## cls.root = Tk() +## +## @classmethod +## def tearDownClass(cls): +## cls.root.destroy() +## del cls.root + + def test_init(self): + self.assertTrue(True) # Get coverage of import + + +# Classes GUIProxy, IdbAdapter, FrameProxy, CodeProxy, DictProxy, +# GUIAdapter, IdbProxy plus 7 module functions. + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_debugobj.py b/Lib/idlelib/idle_test/test_debugobj.py new file mode 100644 index 00000000000..131ce22b8bb --- /dev/null +++ b/Lib/idlelib/idle_test/test_debugobj.py @@ -0,0 +1,57 @@ +"Test debugobj, coverage 40%." + +from idlelib import debugobj +import unittest + + +class ObjectTreeItemTest(unittest.TestCase): + + def test_init(self): + ti = debugobj.ObjectTreeItem('label', 22) + self.assertEqual(ti.labeltext, 'label') + self.assertEqual(ti.object, 22) + self.assertEqual(ti.setfunction, None) + + +class ClassTreeItemTest(unittest.TestCase): + + def test_isexpandable(self): + ti = debugobj.ClassTreeItem('label', 0) + self.assertTrue(ti.IsExpandable()) + + +class AtomicObjectTreeItemTest(unittest.TestCase): + + def test_isexpandable(self): + ti = debugobj.AtomicObjectTreeItem('label', 0) + self.assertFalse(ti.IsExpandable()) + + +class SequenceTreeItemTest(unittest.TestCase): + + def test_isexpandable(self): + ti = debugobj.SequenceTreeItem('label', ()) + self.assertFalse(ti.IsExpandable()) + ti = debugobj.SequenceTreeItem('label', (1,)) + self.assertTrue(ti.IsExpandable()) + + def test_keys(self): + ti = debugobj.SequenceTreeItem('label', 'abc') + self.assertEqual(list(ti.keys()), [0, 1, 2]) + + +class DictTreeItemTest(unittest.TestCase): + + def test_isexpandable(self): + ti = debugobj.DictTreeItem('label', {}) + self.assertFalse(ti.IsExpandable()) + ti = debugobj.DictTreeItem('label', {1:1}) + self.assertTrue(ti.IsExpandable()) + + def test_keys(self): + ti = debugobj.DictTreeItem('label', {1:1, 0:0, 2:2}) + self.assertEqual(ti.keys(), [0, 1, 2]) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_debugobj_r.py b/Lib/idlelib/idle_test/test_debugobj_r.py new file mode 100644 index 00000000000..86e51b6cb2c --- /dev/null +++ b/Lib/idlelib/idle_test/test_debugobj_r.py @@ -0,0 +1,22 @@ +"Test debugobj_r, coverage 56%." + +from idlelib import debugobj_r +import unittest + + +class WrappedObjectTreeItemTest(unittest.TestCase): + + def test_getattr(self): + ti = debugobj_r.WrappedObjectTreeItem(list) + self.assertEqual(ti.append, list.append) + +class StubObjectTreeItemTest(unittest.TestCase): + + def test_init(self): + ti = debugobj_r.StubObjectTreeItem('socket', 1111) + self.assertEqual(ti.sockio, 'socket') + self.assertEqual(ti.oid, 1111) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_delegator.py b/Lib/idlelib/idle_test/test_delegator.py index 85624fbc127..922416297a4 100644 --- a/Lib/idlelib/idle_test/test_delegator.py +++ b/Lib/idlelib/idle_test/test_delegator.py @@ -1,5 +1,8 @@ -import unittest +"Test delegator, coverage 100%." + from idlelib.delegator import Delegator +import unittest + class DelegatorTest(unittest.TestCase): @@ -36,5 +39,6 @@ class DelegatorTest(unittest.TestCase): self.assertEqual(mydel._Delegator__cache, set()) self.assertIs(mydel.delegate, float) + if __name__ == '__main__': unittest.main(verbosity=2, exit=2) diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py index 64a2a88b7e3..12bc8473668 100644 --- a/Lib/idlelib/idle_test/test_editor.py +++ b/Lib/idlelib/idle_test/test_editor.py @@ -1,14 +1,46 @@ -import unittest -from idlelib.editor import EditorWindow +"Test editor, coverage 35%." + +from idlelib import editor +import unittest +from test.support import requires +from tkinter import Tk + +Editor = editor.EditorWindow + + +class EditorWindowTest(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) + cls.root.destroy() + del cls.root + + def test_init(self): + e = Editor(root=self.root) + self.assertEqual(e.root, self.root) + e._close() + + +class EditorFunctionTest(unittest.TestCase): -class Editor_func_test(unittest.TestCase): def test_filename_to_unicode(self): - func = EditorWindow._filename_to_unicode - class dummy(): filesystemencoding = 'utf-8' + func = Editor._filename_to_unicode + class dummy(): + filesystemencoding = 'utf-8' pairs = (('abc', 'abc'), ('a\U00011111c', 'a\ufffdc'), (b'abc', 'abc'), (b'a\xf0\x91\x84\x91c', 'a\ufffdc')) for inp, out in pairs: self.assertEqual(func(dummy, inp), out) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_filelist.py b/Lib/idlelib/idle_test/test_filelist.py new file mode 100644 index 00000000000..731f1975e50 --- /dev/null +++ b/Lib/idlelib/idle_test/test_filelist.py @@ -0,0 +1,33 @@ +"Test filelist, coverage 19%." + +from idlelib import filelist +import unittest +from test.support import requires +from tkinter import Tk + +class FileListTest(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) + cls.root.destroy() + del cls.root + + def test_new_empty(self): + flist = filelist.FileList(self.root) + self.assertEqual(flist.root, self.root) + e = flist.new() + self.assertEqual(type(e), flist.EditorWindow) + e._close() + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_grep.py b/Lib/idlelib/idle_test/test_grep.py index 6b54c131315..ab0d7860f78 100644 --- a/Lib/idlelib/idle_test/test_grep.py +++ b/Lib/idlelib/idle_test/test_grep.py @@ -3,14 +3,15 @@ Non-gui unit tests for grep.GrepDialog methods. dummy_command calls grep_it calls findfiles. An exception raised in one method will fail callers. Otherwise, tests are mostly independent. -*** Currently only test grep_it. +Currently only test grep_it, coverage 51%. """ +from idlelib.grep import GrepDialog import unittest from test.support import captured_stdout from idlelib.idle_test.mock_tk import Var -from idlelib.grep import GrepDialog import re + class Dummy_searchengine: '''GrepDialog.__init__ calls parent SearchDiabolBase which attaches the passed in SearchEngine instance as attribute 'engine'. Only a few of the @@ -21,6 +22,7 @@ class Dummy_searchengine: searchengine = Dummy_searchengine() + class Dummy_grep: # Methods tested #default_command = GrepDialog.default_command @@ -34,6 +36,7 @@ class Dummy_grep: grep = Dummy_grep() + class FindfilesTest(unittest.TestCase): # findfiles is really a function, not a method, could be iterator # test that filename return filename @@ -41,6 +44,7 @@ class FindfilesTest(unittest.TestCase): # test that recursive flag adds idle_test .py files pass + class Grep_itTest(unittest.TestCase): # Test captured reports with 0 and some hits. # Should test file names, but Windows reports have mixed / and \ separators @@ -71,10 +75,12 @@ class Grep_itTest(unittest.TestCase): self.assertIn('2', lines[3]) # hits found 2 self.assertTrue(lines[4].startswith('(Hint:')) + class Default_commandTest(unittest.TestCase): # To write this, move outwin import to top of GrepDialog # so it can be replaced by captured_stdout in class setup/teardown. pass + if __name__ == '__main__': - unittest.main(verbosity=2, exit=False) + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_help.py b/Lib/idlelib/idle_test/test_help.py index 2c68e23b328..b5426599818 100644 --- a/Lib/idlelib/idle_test/test_help.py +++ b/Lib/idlelib/idle_test/test_help.py @@ -1,13 +1,12 @@ -'''Test idlelib.help. +"Test help, coverage 87%." -Coverage: 87% -''' from idlelib import help +import unittest from test.support import requires requires('gui') from os.path import abspath, dirname, join from tkinter import Tk -import unittest + class HelpFrameTest(unittest.TestCase): @@ -30,5 +29,6 @@ class HelpFrameTest(unittest.TestCase): text = self.frame.text self.assertEqual(text.get('1.0', '1.end'), ' IDLE ') + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-06-14-11-35-50.bpo-33855.XL230W.rst b/Misc/NEWS.d/next/IDLE/2018-06-14-11-35-50.bpo-33855.XL230W.rst new file mode 100644 index 00000000000..aaf4f8fe2b0 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-06-14-11-35-50.bpo-33855.XL230W.rst @@ -0,0 +1,2 @@ +Minimally test all IDLE modules. Add missing files, import module, +instantiate classes, and check coverage. Check existing files.