1"Test browser, coverage 90%." 2 3from idlelib import browser 4from test.support import requires 5import unittest 6from unittest import mock 7from idlelib.idle_test.mock_idle import Func 8 9from collections import deque 10import os.path 11import pyclbr 12from tkinter import Tk 13 14from idlelib.tree import TreeNode 15 16 17class ModuleBrowserTest(unittest.TestCase): 18 19 @classmethod 20 def setUpClass(cls): 21 requires('gui') 22 cls.root = Tk() 23 cls.root.withdraw() 24 cls.mb = browser.ModuleBrowser(cls.root, __file__, _utest=True) 25 26 @classmethod 27 def tearDownClass(cls): 28 cls.mb.close() 29 cls.root.update_idletasks() 30 cls.root.destroy() 31 del cls.root, cls.mb 32 33 def test_init(self): 34 mb = self.mb 35 eq = self.assertEqual 36 eq(mb.path, __file__) 37 eq(pyclbr._modules, {}) 38 self.assertIsInstance(mb.node, TreeNode) 39 self.assertIsNotNone(browser.file_open) 40 41 def test_settitle(self): 42 mb = self.mb 43 self.assertIn(os.path.basename(__file__), mb.top.title()) 44 self.assertEqual(mb.top.iconname(), 'Module Browser') 45 46 def test_rootnode(self): 47 mb = self.mb 48 rn = mb.rootnode() 49 self.assertIsInstance(rn, browser.ModuleBrowserTreeItem) 50 51 def test_close(self): 52 mb = self.mb 53 mb.top.destroy = Func() 54 mb.node.destroy = Func() 55 mb.close() 56 self.assertTrue(mb.top.destroy.called) 57 self.assertTrue(mb.node.destroy.called) 58 del mb.top.destroy, mb.node.destroy 59 60 61# Nested tree same as in test_pyclbr.py except for supers on C0. C1. 62mb = pyclbr 63module, fname = 'test', 'test.py' 64C0 = mb.Class(module, 'C0', ['base'], fname, 1, end_lineno=9) 65F1 = mb._nest_function(C0, 'F1', 3, 5) 66C1 = mb._nest_class(C0, 'C1', 6, 9, ['']) 67C2 = mb._nest_class(C1, 'C2', 7, 9) 68F3 = mb._nest_function(C2, 'F3', 9, 9) 69f0 = mb.Function(module, 'f0', fname, 11, end_lineno=15) 70f1 = mb._nest_function(f0, 'f1', 12, 14) 71f2 = mb._nest_function(f1, 'f2', 13, 13) 72c1 = mb._nest_class(f0, 'c1', 15, 15) 73mock_pyclbr_tree = {'C0': C0, 'f0': f0} 74 75# Adjust C0.name, C1.name so tests do not depend on order. 76browser.transform_children(mock_pyclbr_tree, 'test') # C0(base) 77browser.transform_children(C0.children) # C1() 78 79# The class below checks that the calls above are correct 80# and that duplicate calls have no effect. 81 82 83class TransformChildrenTest(unittest.TestCase): 84 85 def test_transform_module_children(self): 86 eq = self.assertEqual 87 transform = browser.transform_children 88 # Parameter matches tree module. 89 tcl = list(transform(mock_pyclbr_tree, 'test')) 90 eq(tcl, [C0, f0]) 91 eq(tcl[0].name, 'C0(base)') 92 eq(tcl[1].name, 'f0') 93 # Check that second call does not change suffix. 94 tcl = list(transform(mock_pyclbr_tree, 'test')) 95 eq(tcl[0].name, 'C0(base)') 96 # Nothing to traverse if parameter name isn't same as tree module. 97 tcl = list(transform(mock_pyclbr_tree, 'different name')) 98 eq(tcl, []) 99 100 def test_transform_node_children(self): 101 eq = self.assertEqual 102 transform = browser.transform_children 103 # Class with two children, one name altered. 104 tcl = list(transform(C0.children)) 105 eq(tcl, [F1, C1]) 106 eq(tcl[0].name, 'F1') 107 eq(tcl[1].name, 'C1()') 108 tcl = list(transform(C0.children)) 109 eq(tcl[1].name, 'C1()') 110 # Function with two children. 111 eq(list(transform(f0.children)), [f1, c1]) 112 113 114class ModuleBrowserTreeItemTest(unittest.TestCase): 115 116 @classmethod 117 def setUpClass(cls): 118 cls.mbt = browser.ModuleBrowserTreeItem(fname) 119 120 def test_init(self): 121 self.assertEqual(self.mbt.file, fname) 122 123 def test_gettext(self): 124 self.assertEqual(self.mbt.GetText(), fname) 125 126 def test_geticonname(self): 127 self.assertEqual(self.mbt.GetIconName(), 'python') 128 129 def test_isexpandable(self): 130 self.assertTrue(self.mbt.IsExpandable()) 131 132 def test_listchildren(self): 133 save_rex = browser.pyclbr.readmodule_ex 134 save_tc = browser.transform_children 135 browser.pyclbr.readmodule_ex = Func(result=mock_pyclbr_tree) 136 browser.transform_children = Func(result=[f0, C0]) 137 try: 138 self.assertEqual(self.mbt.listchildren(), [f0, C0]) 139 finally: 140 browser.pyclbr.readmodule_ex = save_rex 141 browser.transform_children = save_tc 142 143 def test_getsublist(self): 144 mbt = self.mbt 145 mbt.listchildren = Func(result=[f0, C0]) 146 sub0, sub1 = mbt.GetSubList() 147 del mbt.listchildren 148 self.assertIsInstance(sub0, browser.ChildBrowserTreeItem) 149 self.assertIsInstance(sub1, browser.ChildBrowserTreeItem) 150 self.assertEqual(sub0.name, 'f0') 151 self.assertEqual(sub1.name, 'C0(base)') 152 153 @mock.patch('idlelib.browser.file_open') 154 def test_ondoubleclick(self, fopen): 155 mbt = self.mbt 156 157 with mock.patch('os.path.exists', return_value=False): 158 mbt.OnDoubleClick() 159 fopen.assert_not_called() 160 161 with mock.patch('os.path.exists', return_value=True): 162 mbt.OnDoubleClick() 163 fopen.assert_called() 164 fopen.called_with(fname) 165 166 167class ChildBrowserTreeItemTest(unittest.TestCase): 168 169 @classmethod 170 def setUpClass(cls): 171 CBT = browser.ChildBrowserTreeItem 172 cls.cbt_f1 = CBT(f1) 173 cls.cbt_C1 = CBT(C1) 174 cls.cbt_F1 = CBT(F1) 175 176 @classmethod 177 def tearDownClass(cls): 178 del cls.cbt_C1, cls.cbt_f1, cls.cbt_F1 179 180 def test_init(self): 181 eq = self.assertEqual 182 eq(self.cbt_C1.name, 'C1()') 183 self.assertFalse(self.cbt_C1.isfunction) 184 eq(self.cbt_f1.name, 'f1') 185 self.assertTrue(self.cbt_f1.isfunction) 186 187 def test_gettext(self): 188 self.assertEqual(self.cbt_C1.GetText(), 'class C1()') 189 self.assertEqual(self.cbt_f1.GetText(), 'def f1(...)') 190 191 def test_geticonname(self): 192 self.assertEqual(self.cbt_C1.GetIconName(), 'folder') 193 self.assertEqual(self.cbt_f1.GetIconName(), 'python') 194 195 def test_isexpandable(self): 196 self.assertTrue(self.cbt_C1.IsExpandable()) 197 self.assertTrue(self.cbt_f1.IsExpandable()) 198 self.assertFalse(self.cbt_F1.IsExpandable()) 199 200 def test_getsublist(self): 201 eq = self.assertEqual 202 CBT = browser.ChildBrowserTreeItem 203 204 f1sublist = self.cbt_f1.GetSubList() 205 self.assertIsInstance(f1sublist[0], CBT) 206 eq(len(f1sublist), 1) 207 eq(f1sublist[0].name, 'f2') 208 209 eq(self.cbt_F1.GetSubList(), []) 210 211 @mock.patch('idlelib.browser.file_open') 212 def test_ondoubleclick(self, fopen): 213 goto = fopen.return_value.gotoline = mock.Mock() 214 self.cbt_F1.OnDoubleClick() 215 fopen.assert_called() 216 goto.assert_called() 217 goto.assert_called_with(self.cbt_F1.obj.lineno) 218 # Failure test would have to raise OSError or AttributeError. 219 220 221class NestedChildrenTest(unittest.TestCase): 222 "Test that all the nodes in a nested tree are added to the BrowserTree." 223 224 def test_nested(self): 225 queue = deque() 226 actual_names = [] 227 # The tree items are processed in breadth first order. 228 # Verify that processing each sublist hits every node and 229 # in the right order. 230 expected_names = ['f0', 'C0(base)', 231 'f1', 'c1', 'F1', 'C1()', 232 'f2', 'C2', 233 'F3'] 234 CBT = browser.ChildBrowserTreeItem 235 queue.extend((CBT(f0), CBT(C0))) 236 while queue: 237 cb = queue.popleft() 238 sublist = cb.GetSubList() 239 queue.extend(sublist) 240 self.assertIn(cb.name, cb.GetText()) 241 self.assertIn(cb.GetIconName(), ('python', 'folder')) 242 self.assertIs(cb.IsExpandable(), sublist != []) 243 actual_names.append(cb.name) 244 self.assertEqual(actual_names, expected_names) 245 246 247if __name__ == '__main__': 248 unittest.main(verbosity=2) 249