Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 525168b

Browse files
committed
Issue #18592: Add unittests for SearchDialogBase. Patch by Phil Webster.
1 parent f5ac57d commit 525168b

2 files changed

Lines changed: 213 additions & 10 deletions

File tree

Lib/idlelib/SearchDialogBase.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ class SearchDialogBase:
1616
(make_button, create_command_buttons).
1717
These are bound to functions that execute the command.
1818
19-
Except for command buttons, this base class is not limited to
20-
items common to all three subclasses. Rather, it is the Find dialog
21-
minus the "Find Next" command and its execution function.
22-
The other dialogs override methods to replace and add widgets.
19+
Except for command buttons, this base class is not limited to items
20+
common to all three subclasses. Rather, it is the Find dialog minus
21+
the "Find Next" command, its execution function, and the
22+
default_command attribute needed in create_widgets. The other
23+
dialogs override attributes and methods, the latter to replace and
24+
add widgets.
2325
'''
2426

2527
title = "Search Dialog" # replace in subclasses
@@ -30,9 +32,10 @@ def __init__(self, root, engine):
3032
'''Initialize root, engine, and top attributes.
3133
3234
top (level widget): set in create_widgets() called from open().
33-
text (Text being searched): set in open(), only used in subclasses().
35+
text (Text searched): set in open(), only used in subclasses().
3436
ent (ry): created in make_entry() called from create_entry().
3537
row (of grid): 0 in create_widgets(), +1 in make_entry/frame().
38+
default_command: set in subclasses, used in create_widgers().
3639
3740
title (of dialog): class attribute, override in subclasses.
3841
icon (of dialog): ditto, use unclear if cannot minimize dialog.
@@ -93,25 +96,27 @@ def make_entry(self, label, var):
9396
e = Entry(self.top, textvariable=var, exportselection=0)
9497
e.grid(row=self.row, column=1, sticky="nwe")
9598
self.row = self.row + 1
96-
return e
99+
return l, e # return label for testing
97100

98101
def create_entries(self):
99102
"Create one or more entry lines with make_entry."
100-
self.ent = self.make_entry("Find:", self.engine.patvar)
103+
self.ent = self.make_entry("Find:", self.engine.patvar)[1]
101104

102105
def make_frame(self,labeltext=None):
103106
"Return gridded labeled Frame for option or other buttons."
104107
if labeltext:
105108
l = Label(self.top, text=labeltext)
106109
l.grid(row=self.row, column=0, sticky="nw")
110+
else:
111+
l = ''
107112
f = Frame(self.top)
108113
f.grid(row=self.row, column=1, columnspan=1, sticky="nwe")
109114
self.row = self.row + 1
110-
return f
115+
return l, f
111116

112117
def create_option_buttons(self):
113118
"Fill frame with Checkbuttons bound to SearchEngine booleanvars."
114-
f = self.make_frame("Options")
119+
f = self.make_frame("Options")[1]
115120

116121
btn = Checkbutton(f, anchor="w",
117122
variable=self.engine.revar,
@@ -144,7 +149,7 @@ def create_option_buttons(self):
144149

145150
def create_other_buttons(self):
146151
"Fill frame with buttons tied to other options."
147-
f = self.make_frame("Direction")
152+
f = self.make_frame("Direction")[1]
148153

149154
btn = Radiobutton(f, anchor="w",
150155
variable=self.engine.backvar, value=1,
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
'''Unittests for idlelib/SearchDialogBase.py
2+
3+
Coverage: 99%. The only thing not covered is inconsequential --
4+
testing skipping of suite when self.needwrapbutton is false.
5+
6+
'''
7+
import unittest
8+
from test.support import requires
9+
from tkinter import Tk, Toplevel, Frame, Label, BooleanVar, StringVar
10+
from idlelib import SearchEngine as se
11+
from idlelib import SearchDialogBase as sdb
12+
from idlelib.idle_test.mock_idle import Func
13+
from idlelib.idle_test.mock_tk import Var, Mbox
14+
15+
# The following could help make some tests gui-free.
16+
# However, they currently make radiobutton tests fail.
17+
##def setUpModule():
18+
## # Replace tk objects used to initialize se.SearchEngine.
19+
## se.BooleanVar = Var
20+
## se.StringVar = Var
21+
##
22+
##def tearDownModule():
23+
## se.BooleanVar = BooleanVar
24+
## se.StringVar = StringVar
25+
26+
class SearchDialogBaseTest(unittest.TestCase):
27+
28+
@classmethod
29+
def setUpClass(cls):
30+
requires('gui')
31+
cls.root = Tk()
32+
33+
@classmethod
34+
def tearDownClass(cls):
35+
cls.root.destroy()
36+
del cls.root
37+
38+
def setUp(self):
39+
self.engine = se.SearchEngine(self.root) # None also seems to work
40+
self.dialog = sdb.SearchDialogBase(root=self.root, engine=self.engine)
41+
42+
def tearDown(self):
43+
self.dialog.close()
44+
45+
def test_open_and_close(self):
46+
# open calls create_widgets, which needs default_command
47+
self.dialog.default_command = None
48+
49+
# Since text parameter of .open is not used in base class,
50+
# pass dummy 'text' instead of tk.Text().
51+
self.dialog.open('text')
52+
self.assertEqual(self.dialog.top.state(), 'normal')
53+
self.dialog.close()
54+
self.assertEqual(self.dialog.top.state(), 'withdrawn')
55+
56+
self.dialog.open('text', searchphrase="hello")
57+
self.assertEqual(self.dialog.ent.get(), 'hello')
58+
self.dialog.close()
59+
60+
def test_create_widgets(self):
61+
self.dialog.create_entries = Func()
62+
self.dialog.create_option_buttons = Func()
63+
self.dialog.create_other_buttons = Func()
64+
self.dialog.create_command_buttons = Func()
65+
66+
self.dialog.default_command = None
67+
self.dialog.create_widgets()
68+
69+
self.assertTrue(self.dialog.create_entries.called)
70+
self.assertTrue(self.dialog.create_option_buttons.called)
71+
self.assertTrue(self.dialog.create_other_buttons.called)
72+
self.assertTrue(self.dialog.create_command_buttons.called)
73+
74+
def test_make_entry(self):
75+
equal = self.assertEqual
76+
self.dialog.row = 0
77+
self.dialog.top = Toplevel(self.root)
78+
label, entry = self.dialog.make_entry("Test:", 'hello')
79+
equal(label.cget('text'), 'Test:')
80+
81+
self.assertIn(entry.get(), 'hello')
82+
egi = entry.grid_info()
83+
equal(egi['row'], 0)
84+
equal(egi['column'], 1)
85+
equal(egi['rowspan'], 1)
86+
equal(egi['columnspan'], 1)
87+
equal(self.dialog.row, 1)
88+
89+
def test_create_entries(self):
90+
self.dialog.row = 0
91+
self.engine.setpat('hello')
92+
self.dialog.create_entries()
93+
self.assertIn(self.dialog.ent.get(), 'hello')
94+
95+
def test_make_frame(self):
96+
self.dialog.row = 0
97+
self.dialog.top = Toplevel(self.root)
98+
label, frame = self.dialog.make_frame()
99+
self.assertEqual(label, '')
100+
self.assertIsInstance(frame, Frame)
101+
102+
label, labelledframe = self.dialog.make_frame('testlabel')
103+
self.assertEqual(label.cget('text'), 'testlabel')
104+
self.assertIsInstance(labelledframe, Frame)
105+
106+
def btn_test_setup(self, which):
107+
self.dialog.row = 0
108+
self.dialog.top = Toplevel(self.root)
109+
if which == 'option':
110+
self.dialog.create_option_buttons()
111+
elif which == 'other':
112+
self.dialog.create_other_buttons()
113+
else:
114+
raise ValueError('bad which arg %s' % which)
115+
116+
def test_create_option_buttons(self):
117+
self.btn_test_setup('option')
118+
self.checkboxtests()
119+
120+
def test_create_option_buttons_flipped(self):
121+
for var in ('revar', 'casevar', 'wordvar', 'wrapvar'):
122+
Var = getattr(self.engine, var)
123+
Var.set(not Var.get())
124+
self.btn_test_setup('option')
125+
self.checkboxtests(flip=1)
126+
127+
def checkboxtests(self, flip=0):
128+
"""Tests the four checkboxes in the search dialog window."""
129+
engine = self.engine
130+
for child in self.dialog.top.winfo_children():
131+
for grandchild in child.winfo_children():
132+
text = grandchild.config()['text'][-1]
133+
if text == ('Regular', 'expression'):
134+
self.btnstatetest(grandchild, engine.revar, flip)
135+
elif text == ('Match', 'case'):
136+
self.btnstatetest(grandchild, engine.casevar, flip)
137+
elif text == ('Whole', 'word'):
138+
self.btnstatetest(grandchild, engine.wordvar, flip)
139+
elif text == ('Wrap', 'around'):
140+
self.btnstatetest(grandchild, engine.wrapvar, not flip)
141+
142+
def btnstatetest(self, button, var, defaultstate):
143+
self.assertEqual(var.get(), defaultstate)
144+
if defaultstate == 1:
145+
button.deselect()
146+
else:
147+
button.select()
148+
self.assertEqual(var.get(), 1 - defaultstate)
149+
150+
def test_create_other_buttons(self):
151+
self.btn_test_setup('other')
152+
self.radiobuttontests()
153+
154+
def test_create_other_buttons_flipped(self):
155+
self.engine.backvar.set(1)
156+
self.btn_test_setup('other')
157+
self.radiobuttontests(back=1)
158+
159+
def radiobuttontests(self, back=0):
160+
searchupbtn = None
161+
searchdownbtn = None
162+
163+
for child in self.dialog.top.winfo_children():
164+
for grandchild in child.children.values():
165+
text = grandchild.config()['text'][-1]
166+
if text == 'Up':
167+
searchupbtn = grandchild
168+
elif text == 'Down':
169+
searchdownbtn = grandchild
170+
171+
# Defaults to searching downward
172+
self.assertEqual(self.engine.backvar.get(), back)
173+
if back:
174+
searchdownbtn.select()
175+
else:
176+
searchupbtn.select()
177+
self.assertEqual(self.engine.backvar.get(), not back)
178+
searchdownbtn.select()
179+
180+
def test_make_button(self):
181+
self.dialog.top = Toplevel(self.root)
182+
self.dialog.buttonframe = Frame(self.dialog.top)
183+
btn = self.dialog.make_button('Test', self.dialog.close)
184+
self.assertEqual(btn.cget('text'), 'Test')
185+
186+
def test_create_command_buttons(self):
187+
self.dialog.create_command_buttons()
188+
# Look for close button command in buttonframe
189+
closebuttoncommand = ''
190+
for child in self.dialog.buttonframe.winfo_children():
191+
if child.config()['text'][-1] == 'close':
192+
closebuttoncommand = child.config()['command'][-1]
193+
self.assertIn('close', closebuttoncommand)
194+
195+
196+
197+
if __name__ == '__main__':
198+
unittest.main(verbosity=2, exit=2)

0 commit comments

Comments
 (0)