diff options
author | Terry Jan Reedy <tjreedy@udel.edu> | 2014-06-04 00:54:15 (GMT) |
---|---|---|
committer | Terry Jan Reedy <tjreedy@udel.edu> | 2014-06-04 00:54:15 (GMT) |
commit | 8ba9e450c99230d9f8e611ce08edf72dbd7973c7 (patch) | |
tree | 9f0b247cd32690b8c480fbf52c7a3a376c35bc29 /Lib | |
parent | 1e927094d553d776eda713096b6e293048fb2976 (diff) | |
download | cpython-8ba9e450c99230d9f8e611ce08edf72dbd7973c7.zip cpython-8ba9e450c99230d9f8e611ce08edf72dbd7973c7.tar.gz cpython-8ba9e450c99230d9f8e611ce08edf72dbd7973c7.tar.bz2 |
Issue #18409: Idle: add unittest for AutoComplete. Patch by Phil Webster.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/idlelib/AutoComplete.py | 5 | ||||
-rw-r--r-- | Lib/idlelib/idle_test/mock_idle.py | 17 | ||||
-rw-r--r-- | Lib/idlelib/idle_test/mock_tk.py | 27 | ||||
-rw-r--r-- | Lib/idlelib/idle_test/test_autocomplete.py | 136 |
4 files changed, 181 insertions, 4 deletions
diff --git a/Lib/idlelib/AutoComplete.py b/Lib/idlelib/AutoComplete.py index cb38691..1248f00 100644 --- a/Lib/idlelib/AutoComplete.py +++ b/Lib/idlelib/AutoComplete.py @@ -222,3 +222,8 @@ class AutoComplete: namespace = sys.modules.copy() namespace.update(__main__.__dict__) return eval(name, namespace) + + +if __name__ == '__main__': + from unittest import main + main('idlelib.idle_test.test_autocomplete', verbosity=2) diff --git a/Lib/idlelib/idle_test/mock_idle.py b/Lib/idlelib/idle_test/mock_idle.py index 54834de..0bb84ab 100644 --- a/Lib/idlelib/idle_test/mock_idle.py +++ b/Lib/idlelib/idle_test/mock_idle.py @@ -5,6 +5,22 @@ Attributes and methods will be added as needed for tests. from idlelib.idle_test.mock_tk import Text +class Func(object): + '''Mock function captures args and returns result set by test. + + Most common use will probably be to mock methods. + mock_tk.Var and Mbox_func are special cases of this. + ''' + def __init__(self, result=None): + self.result = result + self.args = None + self.kwds = None + def __call__(self, *args, **kwds): + self.args = args + self.kwds = kwds + return self.result + + class Editor(object): '''Minimally imitate EditorWindow.EditorWindow class. ''' @@ -17,6 +33,7 @@ class Editor(object): last = self.text.index('end') return first, last + class UndoDelegator(object): '''Minimally imitate UndoDelegator,UndoDelegator class. ''' diff --git a/Lib/idlelib/idle_test/mock_tk.py b/Lib/idlelib/idle_test/mock_tk.py index 9ce7090..612ea1a 100644 --- a/Lib/idlelib/idle_test/mock_tk.py +++ b/Lib/idlelib/idle_test/mock_tk.py @@ -1,9 +1,27 @@ """Classes that replace tkinter gui objects used by an object being tested. -A gui object is anything with a master or parent paramenter, which is typically -required in spite of what the doc strings say. +A gui object is anything with a master or parent paramenter, which is +typically required in spite of what the doc strings say. """ +class Event(object): + '''Minimal mock with attributes for testing event handlers. + + This is not a gui object, but is used as an argument for callbacks + that access attributes of the event passed. If a callback ignores + the event, other than the fact that is happened, pass 'event'. + + Keyboard, mouse, window, and other sources generate Event instances. + Event instances have the following attributes: serial (number of + event), time (of event), type (of event as number), widget (in which + event occurred), and x,y (position of mouse). There are other + attributes for specific events, such as keycode for key events. + tkinter.Event.__doc__ has more but is still not complete. + ''' + def __init__(self, **kwds): + "Create event with attributes needed for test" + self.__dict__.update(kwds) + class Var(object): "Use for String/Int/BooleanVar: incomplete" def __init__(self, master=None, value=None, name=None): @@ -20,9 +38,10 @@ class Mbox_func(object): Instead of displaying a message box, the mock's call method saves the arguments as instance attributes, which test functions can then examime. + The test can set the result returned to ask function """ - def __init__(self): - self.result = None # The return for all show funcs + def __init__(self, result=None): + self.result = result # Return None for all show funcs def __call__(self, title, message, *args, **kwds): # Save all args for possible examination by tester self.title = title diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py new file mode 100644 index 0000000..c42588a --- /dev/null +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -0,0 +1,136 @@ +import unittest +from test.test_support import requires +from Tkinter import Tk, Text, TclError + +import idlelib.AutoComplete as ac +import idlelib.AutoCompleteWindow as acw +import idlelib.macosxSupport as mac +from idlelib.EditorWindow import EditorWindow +from idlelib.idle_test.mock_idle import Func +from idlelib.idle_test.mock_tk import Event + +class AutoCompleteWindow: + def complete(): + return + + +class AutoCompleteTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + mac.setupApp(cls.root, None) + cls.editor = EditorWindow(root=cls.root) + cls.text = cls.editor.text + + @classmethod + def tearDownClass(cls): + cls.root.destroy() + del cls.text + del cls.editor + del cls.root + + def setUp(self): + self.editor.text.delete('1.0', 'end') + self.autocomplete = ac.AutoComplete(self.editor) + + def test_init(self): + self.assertEqual(self.autocomplete.editwin, self.editor) + + def test_make_autocomplete_window(self): + testwin = self.autocomplete._make_autocomplete_window() + self.assertIsInstance(testwin, acw.AutoCompleteWindow) + + def test_remove_autocomplete_window(self): + self.autocomplete.autocompletewindow = ( + self.autocomplete._make_autocomplete_window()) + self.autocomplete._remove_autocomplete_window() + self.assertIsNone(self.autocomplete.autocompletewindow) + + def test_force_open_completions_event(self): + # Test that force_open_completions_event calls _open_completions + o_cs = Func() + self.autocomplete.open_completions = o_cs + self.autocomplete.force_open_completions_event('event') + self.assertEqual(o_cs.args, (True, False, True)) + + def test_try_open_completions_event(self): + Equal = self.assertEqual + autocomplete = self.autocomplete + trycompletions = self.autocomplete.try_open_completions_event + o_c_l = Func() + autocomplete._open_completions_later = o_c_l + + # _open_completions_later should not be called with no text in editor + trycompletions('event') + Equal(o_c_l.args, None) + + # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1) + self.text.insert('1.0', 're.') + trycompletions('event') + Equal(o_c_l.args, (False, False, False, 1)) + + # _open_completions_later should be called with COMPLETE_FILES (2) + self.text.delete('1.0', 'end') + self.text.insert('1.0', '"./Lib/') + trycompletions('event') + Equal(o_c_l.args, (False, False, False, 2)) + + def test_autocomplete_event(self): + Equal = self.assertEqual + autocomplete = self.autocomplete + + # Test that the autocomplete event is ignored if user is pressing a + # modifier key in addition to the tab key + ev = Event(mc_state=True) + self.assertIsNone(autocomplete.autocomplete_event(ev)) + del ev.mc_state + + # If autocomplete window is open, complete() method is called + testwin = self.autocomplete._make_autocomplete_window() + self.text.insert('1.0', 're.') + Equal(self.autocomplete.autocomplete_event(ev), 'break') + + # If autocomplete window is not active or does not exist, + # open_completions is called. Return depends on its return. + autocomplete._remove_autocomplete_window() + o_cs = Func() # .result = None + autocomplete.open_completions = o_cs + Equal(self.autocomplete.autocomplete_event(ev), None) + Equal(o_cs.args, (False, True, True)) + o_cs.result = True + Equal(self.autocomplete.autocomplete_event(ev), 'break') + Equal(o_cs.args, (False, True, True)) + + def test_open_completions_later(self): + # Test that autocomplete._delayed_completion_id is set + pass + + def test_delayed_open_completions(self): + # Test that autocomplete._delayed_completion_id set to None and that + # open_completions only called if insertion index is the same as + # _delayed_completion_index + pass + + def test_open_completions(self): + # Test completions of files and attributes as well as non-completion + # of errors + pass + + def test_fetch_completions(self): + # Test that fetch_completions returns 2 lists: + # For attribute completion, a large list containing all variables, and + # a small list containing non-private variables. + # For file completion, a large list containing all files in the path, + # and a small list containing files that do not start with '.' + pass + + def test_get_entity(self): + # Test that a name is in the namespace of sys.modules and + # __main__.__dict__ + pass + + +if __name__ == '__main__': + unittest.main(verbosity=2) |