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

1"""Test query, coverage 93%. 

2 

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. 

8 

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 

16 

17import sys 

18from unittest import mock 

19from idlelib.idle_test.mock_tk import Var 

20 

21 

22# NON-GUI TESTS 

23 

24class 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 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

42 

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

48 

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

55 

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

63 

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

68 

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

73 

74 

75class SectionNameTest(unittest.TestCase): 

76 "Test SectionName subclass of Query." 

77 

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

86 

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

91 

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

96 

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

101 

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

106 

107 

108class ModuleNameTest(unittest.TestCase): 

109 "Test ModuleName subclass of Query." 

110 

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

119 

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

124 

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

129 

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

134 

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

142 

143 

144class GotoTest(unittest.TestCase): 

145 "Test Goto subclass of Query." 

146 

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 

154 

155 

156# 3 HelpSource test classes each test one method. 

157 

158class HelpsourceBrowsefileTest(unittest.TestCase): 

159 "Test browse_file method of ModuleName subclass of Query." 

160 

161 class Dummy_HelpSource: 

162 browse_file = query.HelpSource.browse_file 

163 pathvar = Var() 

164 

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

181 

182 

183class HelpsourcePathokTest(unittest.TestCase): 

184 "Test path_ok method of HelpSource subclass of Query." 

185 

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

193 

194 orig_platform = query.platform # Set in test_path_ok_file. 

195 @classmethod 

196 def tearDownClass(cls): 

197 query.platform = cls.orig_platform 

198 

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

203 

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

208 

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

217 

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

226 

227 

228class HelpsourceEntryokTest(unittest.TestCase): 

229 "Test entry_ok method of HelpSource subclass of Query." 

230 

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

239 

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

249 

250 

251# 2 CustomRun test classes each test one method. 

252 

253class CustomRunCLIargsokTest(unittest.TestCase): 

254 "Test cli_ok method of the CustomRun subclass of Query." 

255 

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

263 

264 def test_blank_args(self): 

265 dialog = self.Dummy_CustomRun(' ') 1x

266 self.assertEqual(dialog.cli_args_ok(), []) 1x

267 

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

272 

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

278 

279 

280class CustomRunEntryokTest(unittest.TestCase): 

281 "Test entry_ok method of the CustomRun subclass of Query." 

282 

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

289 

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

299 

300 

301# GUI TESTS 

302 

303class QueryGuiTest(unittest.TestCase): 

304 

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() 

312 

313 @classmethod 

314 def tearDownClass(cls): 

315 del cls.dialog.destroy 

316 del cls.dialog 

317 cls.root.destroy() 

318 del cls.root 

319 

320 def setUp(self): 

321 self.dialog.entry.delete(0, 'end') 

322 self.dialog.result = None 

323 self.dialog.destroy.reset_mock() 

324 

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) 

331 

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) 

337 

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) 

344 

345 

346class SectionnameGuiTest(unittest.TestCase): 

347 

348 @classmethod 

349 def setUpClass(cls): 

350 requires('gui') 

351 

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() 

362 

363 

364class ModulenameGuiTest(unittest.TestCase): 

365 

366 @classmethod 

367 def setUpClass(cls): 

368 requires('gui') 

369 

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() 

379 

380 

381class GotoGuiTest(unittest.TestCase): 

382 

383 @classmethod 

384 def setUpClass(cls): 

385 requires('gui') 

386 

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() 

395 

396 

397class HelpsourceGuiTest(unittest.TestCase): 

398 

399 @classmethod 

400 def setUpClass(cls): 

401 requires('gui') 

402 

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() 

415 

416 

417class CustomRunGuiTest(unittest.TestCase): 

418 

419 @classmethod 

420 def setUpClass(cls): 

421 requires('gui') 

422 

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() 

433 

434 

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)