"""Test idlelib.query. Non-gui tests for Query, SectionName, ModuleName, and HelpSource use dummy versions that extract the non-gui methods and add other needed attributes. GUI tests create an instance of each class and simulate entries and button clicks. Subclass tests only target the new code in the subclass definition. The appearance of the widgets is checked by the Query and HelpSource htests. These are run by running query.py. Coverage: 94% (100% for Query and SectionName). 6 of 8 missing are ModuleName exceptions I don't know how to trigger. """ from test.support import requires from tkinter import Tk import unittest from unittest import mock from idlelib.idle_test.mock_tk import Var, Mbox_func from idlelib import query # Mock entry.showerror messagebox so don't need click to continue # when entry_ok and path_ok methods call it to display errors. orig_showerror = query.showerror showerror = Mbox_func() # Instance has __call__ method. def setUpModule(): query.showerror = showerror def tearDownModule(): query.showerror = orig_showerror # NON-GUI TESTS class QueryTest(unittest.TestCase): "Test Query base class." class Dummy_Query: # Test the following Query methods. entry_ok = query.Query.entry_ok ok = query.Query.ok cancel = query.Query.cancel # Add attributes needed for the tests. entry = Var() result = None destroyed = False def destroy(self): self.destroyed = True dialog = Dummy_Query() def setUp(self): showerror.title = None self.dialog.result = None self.dialog.destroyed = False def test_entry_ok_blank(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set(' ') Equal(dialog.entry_ok(), None) Equal((dialog.result, dialog.destroyed), (None, False)) Equal(showerror.title, 'Entry Error') self.assertIn('Blank', showerror.message) def test_entry_ok_good(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set(' good ') Equal(dialog.entry_ok(), 'good') Equal((dialog.result, dialog.destroyed), (None, False)) Equal(showerror.title, None) def test_ok_blank(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set('') dialog.entry.focus_set = mock.Mock() Equal(dialog.ok(), None) self.assertTrue(dialog.entry.focus_set.called) del dialog.entry.focus_set Equal((dialog.result, dialog.destroyed), (None, False)) def test_ok_good(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set('good') Equal(dialog.ok(), None) Equal((dialog.result, dialog.destroyed), ('good', True)) def test_cancel(self): dialog = self.dialog Equal = self.assertEqual Equal(self.dialog.cancel(), None) Equal((dialog.result, dialog.destroyed), (None, True)) class SectionNameTest(unittest.TestCase): "Test SectionName subclass of Query." class Dummy_SectionName: entry_ok = query.SectionName.entry_ok # Function being tested. used_names = ['used'] entry = Var() dialog = Dummy_SectionName() def setUp(self): showerror.title = None def test_blank_section_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set(' ') Equal(dialog.entry_ok(), None) Equal(showerror.title, 'Name Error') self.assertIn('No', showerror.message) def test_used_section_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set('used') Equal(self.dialog.entry_ok(), None) Equal(showerror.title, 'Name Error') self.assertIn('use', showerror.message) def test_long_section_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set('good'*8) Equal(self.dialog.entry_ok(), None) Equal(showerror.title, 'Name Error') self.assertIn('too long', showerror.message) def test_good_section_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set(' good ') Equal(dialog.entry_ok(), 'good') Equal(showerror.title, None) class ModuleNameTest(unittest.TestCase): "Test ModuleName subclass of Query." class Dummy_ModuleName: entry_ok = query.ModuleName.entry_ok # Funtion being tested. text0 = '' entry = Var() dialog = Dummy_ModuleName() def setUp(self): showerror.title = None def test_blank_module_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set(' ') Equal(dialog.entry_ok(), None) Equal(showerror.title, 'Name Error') self.assertIn('No', showerror.message) def test_bogus_module_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set('__name_xyz123_should_not_exist__') Equal(self.dialog.entry_ok(), None) Equal(showerror.title, 'Import Error') self.assertIn('not found', showerror.message) def test_c_source_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set('itertools') Equal(self.dialog.entry_ok(), None) Equal(showerror.title, 'Import Error') self.assertIn('source-based', showerror.message) def test_good_module_name(self): dialog = self.dialog Equal = self.assertEqual dialog.entry.set('idlelib') self.assertTrue(dialog.entry_ok().endswith('__init__.py')) Equal(showerror.title, None) # 3 HelpSource test classes each test one function. orig_platform = query.platform class HelpsourceBrowsefileTest(unittest.TestCase): "Test browse_file method of ModuleName subclass of Query." class Dummy_HelpSource: browse_file = query.HelpSource.browse_file pathvar = Var() dialog = Dummy_HelpSource() def test_file_replaces_path(self): # Path is widget entry, file is file dialog return. dialog = self.dialog for path, func, result in ( # We need all combination to test all (most) code paths. ('', lambda a,b,c:'', ''), ('', lambda a,b,c: __file__, __file__), ('htest', lambda a,b,c:'', 'htest'), ('htest', lambda a,b,c: __file__, __file__)): with self.subTest(): dialog.pathvar.set(path) dialog.askfilename = func dialog.browse_file() self.assertEqual(dialog.pathvar.get(), result) class HelpsourcePathokTest(unittest.TestCase): "Test path_ok method of ModuleName subclass of Query." class Dummy_HelpSource: path_ok = query.HelpSource.path_ok path = Var() dialog = Dummy_HelpSource() @classmethod def tearDownClass(cls): query.platform = orig_platform def setUp(self): showerror.title = None def test_path_ok_blank(self): dialog = self.dialog Equal = self.assertEqual dialog.path.set(' ') Equal(dialog.path_ok(), None) Equal(showerror.title, 'File Path Error') self.assertIn('No help', showerror.message) def test_path_ok_bad(self): dialog = self.dialog Equal = self.assertEqual dialog.path.set(__file__ + 'bad-bad-bad') Equal(dialog.path_ok(), None) Equal(showerror.title, 'File Path Error') self.assertIn('not exist', showerror.message) def test_path_ok_web(self): dialog = self.dialog Equal = self.assertEqual for url in 'www.py.org', 'http://py.org': with self.subTest(): dialog.path.set(url) Equal(dialog.path_ok(), url) Equal(showerror.title, None) def test_path_ok_file(self): dialog = self.dialog Equal = self.assertEqual for platform, prefix in ('darwin', 'file://'), ('other', ''): with self.subTest(): query.platform = platform dialog.path.set(__file__) Equal(dialog.path_ok(), prefix + __file__) Equal(showerror.title, None) class HelpsourceEntryokTest(unittest.TestCase): "Test entry_ok method of ModuleName subclass of Query." class Dummy_HelpSource: entry_ok = query.HelpSource.entry_ok def item_ok(self): return self.name def path_ok(self): return self.path dialog = Dummy_HelpSource() def test_entry_ok_helpsource(self): dialog = self.dialog for name, path, result in ((None, None, None), (None, 'doc.txt', None), ('doc', None, None), ('doc', 'doc.txt', ('doc', 'doc.txt'))): with self.subTest(): dialog.name, dialog.path = name, path self.assertEqual(self.dialog.entry_ok(), result) # GUI TESTS class QueryGuiTest(unittest.TestCase): @classmethod def setUpClass(cls): requires('gui') cls.root = root = Tk() cls.dialog = query.Query(root, 'TEST', 'test', _utest=True) cls.dialog.destroy = mock.Mock() @classmethod def tearDownClass(cls): del cls.dialog cls.root.destroy() del cls.root def setUp(self): self.dialog.entry.delete(0, 'end') self.dialog.result = None self.dialog.destroy.reset_mock() def test_click_ok(self): dialog = self.dialog dialog.entry.insert(0, 'abc') dialog.button_ok.invoke() self.assertEqual(dialog.result, 'abc') self.assertTrue(dialog.destroy.called) def test_click_blank(self): dialog = self.dialog dialog.button_ok.invoke() self.assertEqual(dialog.result, None) self.assertFalse(dialog.destroy.called) def test_click_cancel(self): dialog = self.dialog dialog.entry.insert(0, 'abc') dialog.button_cancel.invoke() self.assertEqual(dialog.result, None) self.assertTrue(dialog.destroy.called) class SectionnameGuiTest(unittest.TestCase): @classmethod def setUpClass(cls): requires('gui') def test_click_section_name(self): root = Tk() dialog = query.SectionName(root, 'T', 't', {'abc'}, _utest=True) Equal = self.assertEqual Equal(dialog.used_names, {'abc'}) dialog.entry.insert(0, 'okay') dialog.button_ok.invoke() Equal(dialog.result, 'okay') del dialog root.destroy() del root class ModulenameGuiTest(unittest.TestCase): @classmethod def setUpClass(cls): requires('gui') def test_click_module_name(self): root = Tk() dialog = query.ModuleName(root, 'T', 't', 'idlelib', _utest=True) Equal = self.assertEqual Equal(dialog.text0, 'idlelib') Equal(dialog.entry.get(), 'idlelib') dialog.button_ok.invoke() self.assertTrue(dialog.result.endswith('__init__.py')) del dialog root.destroy() del root class HelpsourceGuiTest(unittest.TestCase): @classmethod def setUpClass(cls): requires('gui') def test_click_help_source(self): root = Tk() dialog = query.HelpSource(root, 'T', menuitem='__test__', filepath=__file__, _utest=True) Equal = self.assertEqual Equal(dialog.entry.get(), '__test__') Equal(dialog.path.get(), __file__) dialog.button_ok.invoke() Equal(dialog.result, ('__test__', __file__)) del dialog root.destroy() del root if __name__ == '__main__': unittest.main(verbosity=2, exit=False)