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