Coverage for idle_test/test_query.py: 79%
310 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-11 13:22 -0700
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-11 13:22 -0700
1"""Test query, coverage 93%.
3Non-gui tests for Query, SectionName, ModuleName, and HelpSource use
4dummy versions that extract the non-gui methods and add other needed
5attributes. GUI tests create an instance of each class and simulate
6entries and button clicks. Subclass tests only target the new code in
7the subclass definition.
9The appearance of the widgets is checked by the Query and
10HelpSource htests. These are run by running query.py.
11"""
12from idlelib import query
13import unittest
14from test.support import requires
15from tkinter import Tk, END
17import sys
18from unittest import mock
19from idlelib.idle_test.mock_tk import Var
22# NON-GUI TESTS
24class QueryTest(unittest.TestCase):
25 "Test Query base class."
27 class Dummy_Query:
28 # Test the following Query methods.
29 entry_ok = query.Query.entry_ok
30 ok = query.Query.ok
31 cancel = query.Query.cancel
32 # Add attributes and initialization needed for tests.
33 def __init__(self, dummy_entry):
34 self.entry = Var(value=dummy_entry) 1gcdbh
35 self.entry_error = {'text': ''} 1gcdbh
36 self.result = None 1gcdbh
37 self.destroyed = False 1gcdbh
38 def showerror(self, message):
39 self.entry_error['text'] = message 1cb
40 def destroy(self):
41 self.destroyed = True 1gh
43 def test_entry_ok_blank(self):
44 dialog = self.Dummy_Query(' ') 1c
45 self.assertEqual(dialog.entry_ok(), None) 1c
46 self.assertEqual((dialog.result, dialog.destroyed), (None, False)) 1c
47 self.assertIn('blank line', dialog.entry_error['text']) 1c
49 def test_entry_ok_good(self):
50 dialog = self.Dummy_Query(' good ') 1d
51 Equal = self.assertEqual 1d
52 Equal(dialog.entry_ok(), 'good') 1d
53 Equal((dialog.result, dialog.destroyed), (None, False)) 1d
54 Equal(dialog.entry_error['text'], '') 1d
56 def test_ok_blank(self):
57 dialog = self.Dummy_Query('') 1b
58 dialog.entry.focus_set = mock.Mock() 1b
59 self.assertEqual(dialog.ok(), None) 1b
60 self.assertTrue(dialog.entry.focus_set.called) 1b
61 del dialog.entry.focus_set 1b
62 self.assertEqual((dialog.result, dialog.destroyed), (None, False)) 1b
64 def test_ok_good(self):
65 dialog = self.Dummy_Query('good') 1h
66 self.assertEqual(dialog.ok(), None) 1h
67 self.assertEqual((dialog.result, dialog.destroyed), ('good', True)) 1h
69 def test_cancel(self):
70 dialog = self.Dummy_Query('does not matter') 1g
71 self.assertEqual(dialog.cancel(), None) 1g
72 self.assertEqual((dialog.result, dialog.destroyed), (None, True)) 1g
75class SectionNameTest(unittest.TestCase):
76 "Test SectionName subclass of Query."
78 class Dummy_SectionName:
79 entry_ok = query.SectionName.entry_ok # Function being tested.
80 used_names = ['used']
81 def __init__(self, dummy_entry):
82 self.entry = Var(value=dummy_entry) 1mwno
83 self.entry_error = {'text': ''} 1mwno
84 def showerror(self, message):
85 self.entry_error['text'] = message 1mno
87 def test_blank_section_name(self):
88 dialog = self.Dummy_SectionName(' ') 1m
89 self.assertEqual(dialog.entry_ok(), None) 1m
90 self.assertIn('no name', dialog.entry_error['text']) 1m
92 def test_used_section_name(self):
93 dialog = self.Dummy_SectionName('used') 1o
94 self.assertEqual(dialog.entry_ok(), None) 1o
95 self.assertIn('use', dialog.entry_error['text']) 1o
97 def test_long_section_name(self):
98 dialog = self.Dummy_SectionName('good'*8) 1n
99 self.assertEqual(dialog.entry_ok(), None) 1n
100 self.assertIn('longer than 30', dialog.entry_error['text']) 1n
102 def test_good_section_name(self):
103 dialog = self.Dummy_SectionName(' good ') 1w
104 self.assertEqual(dialog.entry_ok(), 'good') 1w
105 self.assertEqual(dialog.entry_error['text'], '') 1w
108class ModuleNameTest(unittest.TestCase):
109 "Test ModuleName subclass of Query."
111 class Dummy_ModuleName:
112 entry_ok = query.ModuleName.entry_ok # Function being tested.
113 text0 = ''
114 def __init__(self, dummy_entry):
115 self.entry = Var(value=dummy_entry) 1pqri
116 self.entry_error = {'text': ''} 1pqri
117 def showerror(self, message):
118 self.entry_error['text'] = message 1pqr
120 def test_blank_module_name(self):
121 dialog = self.Dummy_ModuleName(' ') 1p
122 self.assertEqual(dialog.entry_ok(), None) 1p
123 self.assertIn('no name', dialog.entry_error['text']) 1p
125 def test_bogus_module_name(self):
126 dialog = self.Dummy_ModuleName('__name_xyz123_should_not_exist__') 1q
127 self.assertEqual(dialog.entry_ok(), None) 1q
128 self.assertIn('not found', dialog.entry_error['text']) 1q
130 def test_c_source_name(self):
131 dialog = self.Dummy_ModuleName('itertools') 1r
132 self.assertEqual(dialog.entry_ok(), None) 1r
133 self.assertIn('source-based', dialog.entry_error['text']) 1r
135 def test_good_module_name(self):
136 dialog = self.Dummy_ModuleName('idlelib') 1i
137 self.assertTrue(dialog.entry_ok().endswith('__init__.py')) 1i
138 self.assertEqual(dialog.entry_error['text'], '') 1i
139 dialog = self.Dummy_ModuleName('idlelib.idle') 1i
140 self.assertTrue(dialog.entry_ok().endswith('idle.py')) 1i
141 self.assertEqual(dialog.entry_error['text'], '') 1i
144class GotoTest(unittest.TestCase):
145 "Test Goto subclass of Query."
147 class Dummy_ModuleName:
148 entry_ok = query.Goto.entry_ok # Function being tested.
149 def __init__(self, dummy_entry):
150 self.entry = Var(value=dummy_entry)
151 self.entry_error = {'text': ''}
152 def showerror(self, message):
153 self.entry_error['text'] = message
156# 3 HelpSource test classes each test one method.
158class HelpsourceBrowsefileTest(unittest.TestCase):
159 "Test browse_file method of ModuleName subclass of Query."
161 class Dummy_HelpSource:
162 browse_file = query.HelpSource.browse_file
163 pathvar = Var()
165 def test_file_replaces_path(self):
166 dialog = self.Dummy_HelpSource() 1k
167 # Path is widget entry, either '' or something.
168 # Func return is file dialog return, either '' or something.
169 # Func return should override widget entry.
170 # We need all 4 combinations to test all (most) code paths.
171 for path, func, result in ( 1k
172 ('', lambda a,b,c:'', ''),
173 ('', lambda a,b,c: __file__, __file__),
174 ('htest', lambda a,b,c:'', 'htest'),
175 ('htest', lambda a,b,c: __file__, __file__)):
176 with self.subTest(): 1k
177 dialog.pathvar.set(path) 1k
178 dialog.askfilename = func 1k
179 dialog.browse_file() 1k
180 self.assertEqual(dialog.pathvar.get(), result) 1k
183class HelpsourcePathokTest(unittest.TestCase):
184 "Test path_ok method of HelpSource subclass of Query."
186 class Dummy_HelpSource:
187 path_ok = query.HelpSource.path_ok
188 def __init__(self, dummy_path):
189 self.path = Var(value=dummy_path) 1stef
190 self.path_error = {'text': ''} 1stef
191 def showerror(self, message, widget=None):
192 self.path_error['text'] = message 1st
194 orig_platform = query.platform # Set in test_path_ok_file.
195 @classmethod
196 def tearDownClass(cls):
197 query.platform = cls.orig_platform
199 def test_path_ok_blank(self):
200 dialog = self.Dummy_HelpSource(' ') 1t
201 self.assertEqual(dialog.path_ok(), None) 1t
202 self.assertIn('no help file', dialog.path_error['text']) 1t
204 def test_path_ok_bad(self):
205 dialog = self.Dummy_HelpSource(__file__ + 'bad-bad-bad') 1s
206 self.assertEqual(dialog.path_ok(), None) 1s
207 self.assertIn('not exist', dialog.path_error['text']) 1s
209 def test_path_ok_web(self):
210 dialog = self.Dummy_HelpSource('') 1f
211 Equal = self.assertEqual 1f
212 for url in 'www.py.org', 'http://py.org': 1f
213 with self.subTest(): 1f
214 dialog.path.set(url) 1f
215 self.assertEqual(dialog.path_ok(), url) 1f
216 self.assertEqual(dialog.path_error['text'], '') 1f
218 def test_path_ok_file(self):
219 dialog = self.Dummy_HelpSource('') 1e
220 for platform, prefix in ('darwin', 'file://'), ('other', ''): 1e
221 with self.subTest(): 1e
222 query.platform = platform 1e
223 dialog.path.set(__file__) 1e
224 self.assertEqual(dialog.path_ok(), prefix + __file__) 1e
225 self.assertEqual(dialog.path_error['text'], '') 1e
228class HelpsourceEntryokTest(unittest.TestCase):
229 "Test entry_ok method of HelpSource subclass of Query."
231 class Dummy_HelpSource:
232 entry_ok = query.HelpSource.entry_ok
233 entry_error = {}
234 path_error = {}
235 def item_ok(self):
236 return self.name 1l
237 def path_ok(self):
238 return self.path 1l
240 def test_entry_ok_helpsource(self):
241 dialog = self.Dummy_HelpSource() 1l
242 for name, path, result in ((None, None, None), 1l
243 (None, 'doc.txt', None),
244 ('doc', None, None),
245 ('doc', 'doc.txt', ('doc', 'doc.txt'))):
246 with self.subTest(): 1l
247 dialog.name, dialog.path = name, path 1l
248 self.assertEqual(dialog.entry_ok(), result) 1l
251# 2 CustomRun test classes each test one method.
253class CustomRunCLIargsokTest(unittest.TestCase):
254 "Test cli_ok method of the CustomRun subclass of Query."
256 class Dummy_CustomRun:
257 cli_args_ok = query.CustomRun.cli_args_ok
258 def __init__(self, dummy_entry):
259 self.entry = Var(value=dummy_entry) 1xuv
260 self.entry_error = {'text': ''} 1xuv
261 def showerror(self, message):
262 self.entry_error['text'] = message 1v
264 def test_blank_args(self):
265 dialog = self.Dummy_CustomRun(' ') 1x
266 self.assertEqual(dialog.cli_args_ok(), []) 1x
268 def test_invalid_args(self):
269 dialog = self.Dummy_CustomRun("'no-closing-quote") 1v
270 self.assertEqual(dialog.cli_args_ok(), None) 1v
271 self.assertIn('No closing', dialog.entry_error['text']) 1v
273 def test_good_args(self):
274 args = ['-n', '10', '--verbose', '-p', '/path', '--name'] 1u
275 dialog = self.Dummy_CustomRun(' '.join(args) + ' "my name"') 1u
276 self.assertEqual(dialog.cli_args_ok(), args + ["my name"]) 1u
277 self.assertEqual(dialog.entry_error['text'], '') 1u
280class CustomRunEntryokTest(unittest.TestCase):
281 "Test entry_ok method of the CustomRun subclass of Query."
283 class Dummy_CustomRun:
284 entry_ok = query.CustomRun.entry_ok
285 entry_error = {}
286 restartvar = Var()
287 def cli_args_ok(self):
288 return self.cli_args 1j
290 def test_entry_ok_customrun(self):
291 dialog = self.Dummy_CustomRun() 1j
292 for restart in {True, False}: 1j
293 dialog.restartvar.set(restart) 1j
294 for cli_args, result in ((None, None), 1j
295 (['my arg'], (['my arg'], restart))):
296 with self.subTest(restart=restart, cli_args=cli_args): 1j
297 dialog.cli_args = cli_args 1j
298 self.assertEqual(dialog.entry_ok(), result) 1j
301# GUI TESTS
303class QueryGuiTest(unittest.TestCase):
305 @classmethod
306 def setUpClass(cls):
307 requires('gui')
308 cls.root = root = Tk()
309 cls.root.withdraw()
310 cls.dialog = query.Query(root, 'TEST', 'test', _utest=True)
311 cls.dialog.destroy = mock.Mock()
313 @classmethod
314 def tearDownClass(cls):
315 del cls.dialog.destroy
316 del cls.dialog
317 cls.root.destroy()
318 del cls.root
320 def setUp(self):
321 self.dialog.entry.delete(0, 'end')
322 self.dialog.result = None
323 self.dialog.destroy.reset_mock()
325 def test_click_ok(self):
326 dialog = self.dialog
327 dialog.entry.insert(0, 'abc')
328 dialog.button_ok.invoke()
329 self.assertEqual(dialog.result, 'abc')
330 self.assertTrue(dialog.destroy.called)
332 def test_click_blank(self):
333 dialog = self.dialog
334 dialog.button_ok.invoke()
335 self.assertEqual(dialog.result, None)
336 self.assertFalse(dialog.destroy.called)
338 def test_click_cancel(self):
339 dialog = self.dialog
340 dialog.entry.insert(0, 'abc')
341 dialog.button_cancel.invoke()
342 self.assertEqual(dialog.result, None)
343 self.assertTrue(dialog.destroy.called)
346class SectionnameGuiTest(unittest.TestCase):
348 @classmethod
349 def setUpClass(cls):
350 requires('gui')
352 def test_click_section_name(self):
353 root = Tk()
354 root.withdraw()
355 dialog = query.SectionName(root, 'T', 't', {'abc'}, _utest=True)
356 Equal = self.assertEqual
357 self.assertEqual(dialog.used_names, {'abc'})
358 dialog.entry.insert(0, 'okay')
359 dialog.button_ok.invoke()
360 self.assertEqual(dialog.result, 'okay')
361 root.destroy()
364class ModulenameGuiTest(unittest.TestCase):
366 @classmethod
367 def setUpClass(cls):
368 requires('gui')
370 def test_click_module_name(self):
371 root = Tk()
372 root.withdraw()
373 dialog = query.ModuleName(root, 'T', 't', 'idlelib', _utest=True)
374 self.assertEqual(dialog.text0, 'idlelib')
375 self.assertEqual(dialog.entry.get(), 'idlelib')
376 dialog.button_ok.invoke()
377 self.assertTrue(dialog.result.endswith('__init__.py'))
378 root.destroy()
381class GotoGuiTest(unittest.TestCase):
383 @classmethod
384 def setUpClass(cls):
385 requires('gui')
387 def test_click_module_name(self):
388 root = Tk()
389 root.withdraw()
390 dialog = query.Goto(root, 'T', 't', _utest=True)
391 dialog.entry.insert(0, '22')
392 dialog.button_ok.invoke()
393 self.assertEqual(dialog.result, 22)
394 root.destroy()
397class HelpsourceGuiTest(unittest.TestCase):
399 @classmethod
400 def setUpClass(cls):
401 requires('gui')
403 def test_click_help_source(self):
404 root = Tk()
405 root.withdraw()
406 dialog = query.HelpSource(root, 'T', menuitem='__test__',
407 filepath=__file__, _utest=True)
408 Equal = self.assertEqual
409 Equal(dialog.entry.get(), '__test__')
410 Equal(dialog.path.get(), __file__)
411 dialog.button_ok.invoke()
412 prefix = "file://" if sys.platform == 'darwin' else ''
413 Equal(dialog.result, ('__test__', prefix + __file__))
414 root.destroy()
417class CustomRunGuiTest(unittest.TestCase):
419 @classmethod
420 def setUpClass(cls):
421 requires('gui')
423 def test_click_args(self):
424 root = Tk()
425 root.withdraw()
426 dialog = query.CustomRun(root, 'Title',
427 cli_args=['a', 'b=1'], _utest=True)
428 self.assertEqual(dialog.entry.get(), 'a b=1')
429 dialog.entry.insert(END, ' c')
430 dialog.button_ok.invoke()
431 self.assertEqual(dialog.result, (['a', 'b=1', 'c'], True))
432 root.destroy()
435if __name__ == '__main__': 435 ↛ 436line 435 didn't jump to line 436, because the condition on line 435 was never true
436 unittest.main(verbosity=2, exit=False)