Home | History | Annotate | Download | only in idle_test
      1 """Test idlelib.query.
      2 
      3 Non-gui tests for Query, SectionName, ModuleName, and HelpSource use
      4 dummy versions that extract the non-gui methods and add other needed
      5 attributes.  GUI tests create an instance of each class and simulate
      6 entries and button clicks.  Subclass tests only target the new code in
      7 the subclass definition.
      8 
      9 The appearance of the widgets is checked by the Query and
     10 HelpSource htests.  These are run by running query.py.
     11 
     12 Coverage: 94% (100% for Query and SectionName).
     13 6 of 8 missing are ModuleName exceptions I don't know how to trigger.
     14 """
     15 from test.support import requires
     16 import sys
     17 from tkinter import Tk
     18 import unittest
     19 from unittest import mock
     20 from idlelib.idle_test.mock_tk import Var
     21 from idlelib import query
     22 
     23 
     24 # NON-GUI TESTS
     25 
     26 class QueryTest(unittest.TestCase):
     27     "Test Query base class."
     28 
     29     class Dummy_Query:
     30         # Test the following Query methods.
     31         entry_ok = query.Query.entry_ok
     32         ok = query.Query.ok
     33         cancel = query.Query.cancel
     34         # Add attributes and initialization needed for tests.
     35         entry = Var()
     36         entry_error = {}
     37         def __init__(self, dummy_entry):
     38             self.entry.set(dummy_entry)
     39             self.entry_error['text'] = ''
     40             self.result = None
     41             self.destroyed = False
     42         def showerror(self, message):
     43             self.entry_error['text'] = message
     44         def destroy(self):
     45             self.destroyed = True
     46 
     47     def test_entry_ok_blank(self):
     48         dialog = self.Dummy_Query(' ')
     49         self.assertEqual(dialog.entry_ok(), None)
     50         self.assertEqual((dialog.result, dialog.destroyed), (None, False))
     51         self.assertIn('blank line', dialog.entry_error['text'])
     52 
     53     def test_entry_ok_good(self):
     54         dialog = self.Dummy_Query('  good ')
     55         Equal = self.assertEqual
     56         Equal(dialog.entry_ok(), 'good')
     57         Equal((dialog.result, dialog.destroyed), (None, False))
     58         Equal(dialog.entry_error['text'], '')
     59 
     60     def test_ok_blank(self):
     61         dialog = self.Dummy_Query('')
     62         dialog.entry.focus_set = mock.Mock()
     63         self.assertEqual(dialog.ok(), None)
     64         self.assertTrue(dialog.entry.focus_set.called)
     65         del dialog.entry.focus_set
     66         self.assertEqual((dialog.result, dialog.destroyed), (None, False))
     67 
     68     def test_ok_good(self):
     69         dialog = self.Dummy_Query('good')
     70         self.assertEqual(dialog.ok(), None)
     71         self.assertEqual((dialog.result, dialog.destroyed), ('good', True))
     72 
     73     def test_cancel(self):
     74         dialog = self.Dummy_Query('does not matter')
     75         self.assertEqual(dialog.cancel(), None)
     76         self.assertEqual((dialog.result, dialog.destroyed), (None, True))
     77 
     78 
     79 class SectionNameTest(unittest.TestCase):
     80     "Test SectionName subclass of Query."
     81 
     82     class Dummy_SectionName:
     83         entry_ok = query.SectionName.entry_ok  # Function being tested.
     84         used_names = ['used']
     85         entry = Var()
     86         entry_error = {}
     87         def __init__(self, dummy_entry):
     88             self.entry.set(dummy_entry)
     89             self.entry_error['text'] = ''
     90         def showerror(self, message):
     91             self.entry_error['text'] = message
     92 
     93     def test_blank_section_name(self):
     94         dialog = self.Dummy_SectionName(' ')
     95         self.assertEqual(dialog.entry_ok(), None)
     96         self.assertIn('no name', dialog.entry_error['text'])
     97 
     98     def test_used_section_name(self):
     99         dialog = self.Dummy_SectionName('used')
    100         self.assertEqual(dialog.entry_ok(), None)
    101         self.assertIn('use', dialog.entry_error['text'])
    102 
    103     def test_long_section_name(self):
    104         dialog = self.Dummy_SectionName('good'*8)
    105         self.assertEqual(dialog.entry_ok(), None)
    106         self.assertIn('longer than 30', dialog.entry_error['text'])
    107 
    108     def test_good_section_name(self):
    109         dialog = self.Dummy_SectionName('  good ')
    110         self.assertEqual(dialog.entry_ok(), 'good')
    111         self.assertEqual(dialog.entry_error['text'], '')
    112 
    113 
    114 class ModuleNameTest(unittest.TestCase):
    115     "Test ModuleName subclass of Query."
    116 
    117     class Dummy_ModuleName:
    118         entry_ok = query.ModuleName.entry_ok  # Function being tested.
    119         text0 = ''
    120         entry = Var()
    121         entry_error = {}
    122         def __init__(self, dummy_entry):
    123             self.entry.set(dummy_entry)
    124             self.entry_error['text'] = ''
    125         def showerror(self, message):
    126             self.entry_error['text'] = message
    127 
    128     def test_blank_module_name(self):
    129         dialog = self.Dummy_ModuleName(' ')
    130         self.assertEqual(dialog.entry_ok(), None)
    131         self.assertIn('no name', dialog.entry_error['text'])
    132 
    133     def test_bogus_module_name(self):
    134         dialog = self.Dummy_ModuleName('__name_xyz123_should_not_exist__')
    135         self.assertEqual(dialog.entry_ok(), None)
    136         self.assertIn('not found', dialog.entry_error['text'])
    137 
    138     def test_c_source_name(self):
    139         dialog = self.Dummy_ModuleName('itertools')
    140         self.assertEqual(dialog.entry_ok(), None)
    141         self.assertIn('source-based', dialog.entry_error['text'])
    142 
    143     def test_good_module_name(self):
    144         dialog = self.Dummy_ModuleName('idlelib')
    145         self.assertTrue(dialog.entry_ok().endswith('__init__.py'))
    146         self.assertEqual(dialog.entry_error['text'], '')
    147 
    148 
    149 # 3 HelpSource test classes each test one function.
    150 
    151 orig_platform = query.platform
    152 
    153 class HelpsourceBrowsefileTest(unittest.TestCase):
    154     "Test browse_file method of ModuleName subclass of Query."
    155 
    156     class Dummy_HelpSource:
    157         browse_file = query.HelpSource.browse_file
    158         pathvar = Var()
    159 
    160     def test_file_replaces_path(self):
    161         dialog = self.Dummy_HelpSource()
    162         # Path is widget entry, either '' or something.
    163         # Func return is file dialog return, either '' or something.
    164         # Func return should override widget entry.
    165         # We need all 4 combination to test all (most) code paths.
    166         for path, func, result in (
    167                 ('', lambda a,b,c:'', ''),
    168                 ('', lambda a,b,c: __file__, __file__),
    169                 ('htest', lambda a,b,c:'', 'htest'),
    170                 ('htest', lambda a,b,c: __file__, __file__)):
    171             with self.subTest():
    172                 dialog.pathvar.set(path)
    173                 dialog.askfilename = func
    174                 dialog.browse_file()
    175                 self.assertEqual(dialog.pathvar.get(), result)
    176 
    177 
    178 class HelpsourcePathokTest(unittest.TestCase):
    179     "Test path_ok method of HelpSource subclass of Query."
    180 
    181     class Dummy_HelpSource:
    182         path_ok = query.HelpSource.path_ok
    183         path = Var()
    184         path_error = {}
    185         def __init__(self, dummy_path):
    186             self.path.set(dummy_path)
    187             self.path_error['text'] = ''
    188         def showerror(self, message, widget=None):
    189             self.path_error['text'] = message
    190 
    191     @classmethod
    192     def tearDownClass(cls):
    193         query.platform = orig_platform
    194 
    195     def test_path_ok_blank(self):
    196         dialog = self.Dummy_HelpSource(' ')
    197         self.assertEqual(dialog.path_ok(), None)
    198         self.assertIn('no help file', dialog.path_error['text'])
    199 
    200     def test_path_ok_bad(self):
    201         dialog = self.Dummy_HelpSource(__file__ + 'bad-bad-bad')
    202         self.assertEqual(dialog.path_ok(), None)
    203         self.assertIn('not exist', dialog.path_error['text'])
    204 
    205     def test_path_ok_web(self):
    206         dialog = self.Dummy_HelpSource('')
    207         Equal = self.assertEqual
    208         for url in 'www.py.org', 'http://py.org':
    209             with self.subTest():
    210                 dialog.path.set(url)
    211                 self.assertEqual(dialog.path_ok(), url)
    212                 self.assertEqual(dialog.path_error['text'], '')
    213 
    214     def test_path_ok_file(self):
    215         dialog = self.Dummy_HelpSource('')
    216         for platform, prefix in ('darwin', 'file://'), ('other', ''):
    217             with self.subTest():
    218                 query.platform = platform
    219                 dialog.path.set(__file__)
    220                 self.assertEqual(dialog.path_ok(), prefix + __file__)
    221                 self.assertEqual(dialog.path_error['text'], '')
    222 
    223 
    224 class HelpsourceEntryokTest(unittest.TestCase):
    225     "Test entry_ok method of HelpSource subclass of Query."
    226 
    227     class Dummy_HelpSource:
    228         entry_ok = query.HelpSource.entry_ok
    229         entry_error = {}
    230         path_error = {}
    231         def item_ok(self):
    232             return self.name
    233         def path_ok(self):
    234             return self.path
    235 
    236     def test_entry_ok_helpsource(self):
    237         dialog = self.Dummy_HelpSource()
    238         for name, path, result in ((None, None, None),
    239                                    (None, 'doc.txt', None),
    240                                    ('doc', None, None),
    241                                    ('doc', 'doc.txt', ('doc', 'doc.txt'))):
    242             with self.subTest():
    243                 dialog.name, dialog.path = name, path
    244                 self.assertEqual(dialog.entry_ok(), result)
    245 
    246 
    247 # GUI TESTS
    248 
    249 class QueryGuiTest(unittest.TestCase):
    250 
    251     @classmethod
    252     def setUpClass(cls):
    253         requires('gui')
    254         cls.root = root = Tk()
    255         cls.root.withdraw()
    256         cls.dialog = query.Query(root, 'TEST', 'test', _utest=True)
    257         cls.dialog.destroy = mock.Mock()
    258 
    259     @classmethod
    260     def tearDownClass(cls):
    261         del cls.dialog
    262         cls.root.destroy()
    263         del cls.root
    264 
    265     def setUp(self):
    266         self.dialog.entry.delete(0, 'end')
    267         self.dialog.result = None
    268         self.dialog.destroy.reset_mock()
    269 
    270     def test_click_ok(self):
    271         dialog = self.dialog
    272         dialog.entry.insert(0, 'abc')
    273         dialog.button_ok.invoke()
    274         self.assertEqual(dialog.result, 'abc')
    275         self.assertTrue(dialog.destroy.called)
    276 
    277     def test_click_blank(self):
    278         dialog = self.dialog
    279         dialog.button_ok.invoke()
    280         self.assertEqual(dialog.result, None)
    281         self.assertFalse(dialog.destroy.called)
    282 
    283     def test_click_cancel(self):
    284         dialog = self.dialog
    285         dialog.entry.insert(0, 'abc')
    286         dialog.button_cancel.invoke()
    287         self.assertEqual(dialog.result, None)
    288         self.assertTrue(dialog.destroy.called)
    289 
    290 
    291 class SectionnameGuiTest(unittest.TestCase):
    292 
    293     @classmethod
    294     def setUpClass(cls):
    295         requires('gui')
    296 
    297     def test_click_section_name(self):
    298         root = Tk()
    299         root.withdraw()
    300         dialog =  query.SectionName(root, 'T', 't', {'abc'}, _utest=True)
    301         Equal = self.assertEqual
    302         self.assertEqual(dialog.used_names, {'abc'})
    303         dialog.entry.insert(0, 'okay')
    304         dialog.button_ok.invoke()
    305         self.assertEqual(dialog.result, 'okay')
    306         del dialog
    307         root.destroy()
    308         del root
    309 
    310 
    311 class ModulenameGuiTest(unittest.TestCase):
    312 
    313     @classmethod
    314     def setUpClass(cls):
    315         requires('gui')
    316 
    317     def test_click_module_name(self):
    318         root = Tk()
    319         root.withdraw()
    320         dialog =  query.ModuleName(root, 'T', 't', 'idlelib', _utest=True)
    321         self.assertEqual(dialog.text0, 'idlelib')
    322         self.assertEqual(dialog.entry.get(), 'idlelib')
    323         dialog.button_ok.invoke()
    324         self.assertTrue(dialog.result.endswith('__init__.py'))
    325         del dialog
    326         root.destroy()
    327         del root
    328 
    329 
    330 class HelpsourceGuiTest(unittest.TestCase):
    331 
    332     @classmethod
    333     def setUpClass(cls):
    334         requires('gui')
    335 
    336     def test_click_help_source(self):
    337         root = Tk()
    338         root.withdraw()
    339         dialog =  query.HelpSource(root, 'T', menuitem='__test__',
    340                                    filepath=__file__, _utest=True)
    341         Equal = self.assertEqual
    342         Equal(dialog.entry.get(), '__test__')
    343         Equal(dialog.path.get(), __file__)
    344         dialog.button_ok.invoke()
    345         prefix = "file://" if sys.platform == 'darwin' else ''
    346         Equal(dialog.result, ('__test__', prefix + __file__))
    347         del dialog
    348         root.destroy()
    349         del root
    350 
    351 
    352 if __name__ == '__main__':
    353     unittest.main(verbosity=2, exit=False)
    354