ยปCore Development>Code coverage>Lib/tkinter/test/widget_tests.py

Python code coverage for Lib/tkinter/test/widget_tests.py

#countcontent
1n/a# Common tests for test_tkinter/test_widgets.py and test_ttk/test_widgets.py
2n/a
3n/aimport unittest
4n/aimport sys
5n/aimport tkinter
6n/afrom tkinter.ttk import Scale
7n/afrom tkinter.test.support import (AbstractTkTest, tcl_version, requires_tcl,
8n/a get_tk_patchlevel, pixels_conv, tcl_obj_eq)
9n/aimport test.support
10n/a
11n/a
12n/anoconv = False
13n/aif get_tk_patchlevel() < (8, 5, 11):
14n/a noconv = str
15n/a
16n/apixels_round = round
17n/aif get_tk_patchlevel()[:3] == (8, 5, 11):
18n/a # Issue #19085: Workaround a bug in Tk
19n/a # http://core.tcl.tk/tk/info/3497848
20n/a pixels_round = int
21n/a
22n/a
23n/a_sentinel = object()
24n/a
25n/aclass AbstractWidgetTest(AbstractTkTest):
26n/a _conv_pixels = staticmethod(pixels_round)
27n/a _conv_pad_pixels = None
28n/a _stringify = False
29n/a
30n/a @property
31n/a def scaling(self):
32n/a try:
33n/a return self._scaling
34n/a except AttributeError:
35n/a self._scaling = float(self.root.call('tk', 'scaling'))
36n/a return self._scaling
37n/a
38n/a def _str(self, value):
39n/a if not self._stringify and self.wantobjects and tcl_version >= (8, 6):
40n/a return value
41n/a if isinstance(value, tuple):
42n/a return ' '.join(map(self._str, value))
43n/a return str(value)
44n/a
45n/a def assertEqual2(self, actual, expected, msg=None, eq=object.__eq__):
46n/a if eq(actual, expected):
47n/a return
48n/a self.assertEqual(actual, expected, msg)
49n/a
50n/a def checkParam(self, widget, name, value, *, expected=_sentinel,
51n/a conv=False, eq=None):
52n/a widget[name] = value
53n/a if expected is _sentinel:
54n/a expected = value
55n/a if conv:
56n/a expected = conv(expected)
57n/a if self._stringify or not self.wantobjects:
58n/a if isinstance(expected, tuple):
59n/a expected = tkinter._join(expected)
60n/a else:
61n/a expected = str(expected)
62n/a if eq is None:
63n/a eq = tcl_obj_eq
64n/a self.assertEqual2(widget[name], expected, eq=eq)
65n/a self.assertEqual2(widget.cget(name), expected, eq=eq)
66n/a # XXX
67n/a if not isinstance(widget, Scale):
68n/a t = widget.configure(name)
69n/a self.assertEqual(len(t), 5)
70n/a self.assertEqual2(t[4], expected, eq=eq)
71n/a
72n/a def checkInvalidParam(self, widget, name, value, errmsg=None, *,
73n/a keep_orig=True):
74n/a orig = widget[name]
75n/a if errmsg is not None:
76n/a errmsg = errmsg.format(value)
77n/a with self.assertRaises(tkinter.TclError) as cm:
78n/a widget[name] = value
79n/a if errmsg is not None:
80n/a self.assertEqual(str(cm.exception), errmsg)
81n/a if keep_orig:
82n/a self.assertEqual(widget[name], orig)
83n/a else:
84n/a widget[name] = orig
85n/a with self.assertRaises(tkinter.TclError) as cm:
86n/a widget.configure({name: value})
87n/a if errmsg is not None:
88n/a self.assertEqual(str(cm.exception), errmsg)
89n/a if keep_orig:
90n/a self.assertEqual(widget[name], orig)
91n/a else:
92n/a widget[name] = orig
93n/a
94n/a def checkParams(self, widget, name, *values, **kwargs):
95n/a for value in values:
96n/a self.checkParam(widget, name, value, **kwargs)
97n/a
98n/a def checkIntegerParam(self, widget, name, *values, **kwargs):
99n/a self.checkParams(widget, name, *values, **kwargs)
100n/a self.checkInvalidParam(widget, name, '',
101n/a errmsg='expected integer but got ""')
102n/a self.checkInvalidParam(widget, name, '10p',
103n/a errmsg='expected integer but got "10p"')
104n/a self.checkInvalidParam(widget, name, 3.2,
105n/a errmsg='expected integer but got "3.2"')
106n/a
107n/a def checkFloatParam(self, widget, name, *values, conv=float, **kwargs):
108n/a for value in values:
109n/a self.checkParam(widget, name, value, conv=conv, **kwargs)
110n/a self.checkInvalidParam(widget, name, '',
111n/a errmsg='expected floating-point number but got ""')
112n/a self.checkInvalidParam(widget, name, 'spam',
113n/a errmsg='expected floating-point number but got "spam"')
114n/a
115n/a def checkBooleanParam(self, widget, name):
116n/a for value in (False, 0, 'false', 'no', 'off'):
117n/a self.checkParam(widget, name, value, expected=0)
118n/a for value in (True, 1, 'true', 'yes', 'on'):
119n/a self.checkParam(widget, name, value, expected=1)
120n/a self.checkInvalidParam(widget, name, '',
121n/a errmsg='expected boolean value but got ""')
122n/a self.checkInvalidParam(widget, name, 'spam',
123n/a errmsg='expected boolean value but got "spam"')
124n/a
125n/a def checkColorParam(self, widget, name, *, allow_empty=None, **kwargs):
126n/a self.checkParams(widget, name,
127n/a '#ff0000', '#00ff00', '#0000ff', '#123456',
128n/a 'red', 'green', 'blue', 'white', 'black', 'grey',
129n/a **kwargs)
130n/a self.checkInvalidParam(widget, name, 'spam',
131n/a errmsg='unknown color name "spam"')
132n/a
133n/a def checkCursorParam(self, widget, name, **kwargs):
134n/a self.checkParams(widget, name, 'arrow', 'watch', 'cross', '',**kwargs)
135n/a if tcl_version >= (8, 5):
136n/a self.checkParam(widget, name, 'none')
137n/a self.checkInvalidParam(widget, name, 'spam',
138n/a errmsg='bad cursor spec "spam"')
139n/a
140n/a def checkCommandParam(self, widget, name):
141n/a def command(*args):
142n/a pass
143n/a widget[name] = command
144n/a self.assertTrue(widget[name])
145n/a self.checkParams(widget, name, '')
146n/a
147n/a def checkEnumParam(self, widget, name, *values, errmsg=None, **kwargs):
148n/a self.checkParams(widget, name, *values, **kwargs)
149n/a if errmsg is None:
150n/a errmsg2 = ' %s "{}": must be %s%s or %s' % (
151n/a name,
152n/a ', '.join(values[:-1]),
153n/a ',' if len(values) > 2 else '',
154n/a values[-1])
155n/a self.checkInvalidParam(widget, name, '',
156n/a errmsg='ambiguous' + errmsg2)
157n/a errmsg = 'bad' + errmsg2
158n/a self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg)
159n/a
160n/a def checkPixelsParam(self, widget, name, *values,
161n/a conv=None, keep_orig=True, **kwargs):
162n/a if conv is None:
163n/a conv = self._conv_pixels
164n/a for value in values:
165n/a expected = _sentinel
166n/a conv1 = conv
167n/a if isinstance(value, str):
168n/a if conv1 and conv1 is not str:
169n/a expected = pixels_conv(value) * self.scaling
170n/a conv1 = round
171n/a self.checkParam(widget, name, value, expected=expected,
172n/a conv=conv1, **kwargs)
173n/a self.checkInvalidParam(widget, name, '6x',
174n/a errmsg='bad screen distance "6x"', keep_orig=keep_orig)
175n/a self.checkInvalidParam(widget, name, 'spam',
176n/a errmsg='bad screen distance "spam"', keep_orig=keep_orig)
177n/a
178n/a def checkReliefParam(self, widget, name):
179n/a self.checkParams(widget, name,
180n/a 'flat', 'groove', 'raised', 'ridge', 'solid', 'sunken')
181n/a errmsg='bad relief "spam": must be '\
182n/a 'flat, groove, raised, ridge, solid, or sunken'
183n/a if tcl_version < (8, 6):
184n/a errmsg = None
185n/a self.checkInvalidParam(widget, name, 'spam',
186n/a errmsg=errmsg)
187n/a
188n/a def checkImageParam(self, widget, name):
189n/a image = tkinter.PhotoImage(master=self.root, name='image1')
190n/a self.checkParam(widget, name, image, conv=str)
191n/a self.checkInvalidParam(widget, name, 'spam',
192n/a errmsg='image "spam" doesn\'t exist')
193n/a widget[name] = ''
194n/a
195n/a def checkVariableParam(self, widget, name, var):
196n/a self.checkParam(widget, name, var, conv=str)
197n/a
198n/a def assertIsBoundingBox(self, bbox):
199n/a self.assertIsNotNone(bbox)
200n/a self.assertIsInstance(bbox, tuple)
201n/a if len(bbox) != 4:
202n/a self.fail('Invalid bounding box: %r' % (bbox,))
203n/a for item in bbox:
204n/a if not isinstance(item, int):
205n/a self.fail('Invalid bounding box: %r' % (bbox,))
206n/a break
207n/a
208n/a
209n/a def test_keys(self):
210n/a widget = self.create()
211n/a keys = widget.keys()
212n/a # XXX
213n/a if not isinstance(widget, Scale):
214n/a self.assertEqual(sorted(keys), sorted(widget.configure()))
215n/a for k in keys:
216n/a widget[k]
217n/a # Test if OPTIONS contains all keys
218n/a if test.support.verbose:
219n/a aliases = {
220n/a 'bd': 'borderwidth',
221n/a 'bg': 'background',
222n/a 'fg': 'foreground',
223n/a 'invcmd': 'invalidcommand',
224n/a 'vcmd': 'validatecommand',
225n/a }
226n/a keys = set(keys)
227n/a expected = set(self.OPTIONS)
228n/a for k in sorted(keys - expected):
229n/a if not (k in aliases and
230n/a aliases[k] in keys and
231n/a aliases[k] in expected):
232n/a print('%s.OPTIONS doesn\'t contain "%s"' %
233n/a (self.__class__.__name__, k))
234n/a
235n/a
236n/aclass StandardOptionsTests:
237n/a STANDARD_OPTIONS = (
238n/a 'activebackground', 'activeborderwidth', 'activeforeground', 'anchor',
239n/a 'background', 'bitmap', 'borderwidth', 'compound', 'cursor',
240n/a 'disabledforeground', 'exportselection', 'font', 'foreground',
241n/a 'highlightbackground', 'highlightcolor', 'highlightthickness',
242n/a 'image', 'insertbackground', 'insertborderwidth',
243n/a 'insertofftime', 'insertontime', 'insertwidth',
244n/a 'jump', 'justify', 'orient', 'padx', 'pady', 'relief',
245n/a 'repeatdelay', 'repeatinterval',
246n/a 'selectbackground', 'selectborderwidth', 'selectforeground',
247n/a 'setgrid', 'takefocus', 'text', 'textvariable', 'troughcolor',
248n/a 'underline', 'wraplength', 'xscrollcommand', 'yscrollcommand',
249n/a )
250n/a
251n/a def test_activebackground(self):
252n/a widget = self.create()
253n/a self.checkColorParam(widget, 'activebackground')
254n/a
255n/a def test_activeborderwidth(self):
256n/a widget = self.create()
257n/a self.checkPixelsParam(widget, 'activeborderwidth',
258n/a 0, 1.3, 2.9, 6, -2, '10p')
259n/a
260n/a def test_activeforeground(self):
261n/a widget = self.create()
262n/a self.checkColorParam(widget, 'activeforeground')
263n/a
264n/a def test_anchor(self):
265n/a widget = self.create()
266n/a self.checkEnumParam(widget, 'anchor',
267n/a 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'center')
268n/a
269n/a def test_background(self):
270n/a widget = self.create()
271n/a self.checkColorParam(widget, 'background')
272n/a if 'bg' in self.OPTIONS:
273n/a self.checkColorParam(widget, 'bg')
274n/a
275n/a def test_bitmap(self):
276n/a widget = self.create()
277n/a self.checkParam(widget, 'bitmap', 'questhead')
278n/a self.checkParam(widget, 'bitmap', 'gray50')
279n/a filename = test.support.findfile('python.xbm', subdir='imghdrdata')
280n/a self.checkParam(widget, 'bitmap', '@' + filename)
281n/a # Cocoa Tk widgets don't detect invalid -bitmap values
282n/a # See https://core.tcl.tk/tk/info/31cd33dbf0
283n/a if not ('aqua' in self.root.tk.call('tk', 'windowingsystem') and
284n/a 'AppKit' in self.root.winfo_server()):
285n/a self.checkInvalidParam(widget, 'bitmap', 'spam',
286n/a errmsg='bitmap "spam" not defined')
287n/a
288n/a def test_borderwidth(self):
289n/a widget = self.create()
290n/a self.checkPixelsParam(widget, 'borderwidth',
291n/a 0, 1.3, 2.6, 6, -2, '10p')
292n/a if 'bd' in self.OPTIONS:
293n/a self.checkPixelsParam(widget, 'bd', 0, 1.3, 2.6, 6, -2, '10p')
294n/a
295n/a def test_compound(self):
296n/a widget = self.create()
297n/a self.checkEnumParam(widget, 'compound',
298n/a 'bottom', 'center', 'left', 'none', 'right', 'top')
299n/a
300n/a def test_cursor(self):
301n/a widget = self.create()
302n/a self.checkCursorParam(widget, 'cursor')
303n/a
304n/a def test_disabledforeground(self):
305n/a widget = self.create()
306n/a self.checkColorParam(widget, 'disabledforeground')
307n/a
308n/a def test_exportselection(self):
309n/a widget = self.create()
310n/a self.checkBooleanParam(widget, 'exportselection')
311n/a
312n/a def test_font(self):
313n/a widget = self.create()
314n/a self.checkParam(widget, 'font',
315n/a '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*')
316n/a self.checkInvalidParam(widget, 'font', '',
317n/a errmsg='font "" doesn\'t exist')
318n/a
319n/a def test_foreground(self):
320n/a widget = self.create()
321n/a self.checkColorParam(widget, 'foreground')
322n/a if 'fg' in self.OPTIONS:
323n/a self.checkColorParam(widget, 'fg')
324n/a
325n/a def test_highlightbackground(self):
326n/a widget = self.create()
327n/a self.checkColorParam(widget, 'highlightbackground')
328n/a
329n/a def test_highlightcolor(self):
330n/a widget = self.create()
331n/a self.checkColorParam(widget, 'highlightcolor')
332n/a
333n/a def test_highlightthickness(self):
334n/a widget = self.create()
335n/a self.checkPixelsParam(widget, 'highlightthickness',
336n/a 0, 1.3, 2.6, 6, '10p')
337n/a self.checkParam(widget, 'highlightthickness', -2, expected=0,
338n/a conv=self._conv_pixels)
339n/a
340n/a @unittest.skipIf(sys.platform == 'darwin',
341n/a 'crashes with Cocoa Tk (issue19733)')
342n/a def test_image(self):
343n/a widget = self.create()
344n/a self.checkImageParam(widget, 'image')
345n/a
346n/a def test_insertbackground(self):
347n/a widget = self.create()
348n/a self.checkColorParam(widget, 'insertbackground')
349n/a
350n/a def test_insertborderwidth(self):
351n/a widget = self.create()
352n/a self.checkPixelsParam(widget, 'insertborderwidth',
353n/a 0, 1.3, 2.6, 6, -2, '10p')
354n/a
355n/a def test_insertofftime(self):
356n/a widget = self.create()
357n/a self.checkIntegerParam(widget, 'insertofftime', 100)
358n/a
359n/a def test_insertontime(self):
360n/a widget = self.create()
361n/a self.checkIntegerParam(widget, 'insertontime', 100)
362n/a
363n/a def test_insertwidth(self):
364n/a widget = self.create()
365n/a self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p')
366n/a
367n/a def test_jump(self):
368n/a widget = self.create()
369n/a self.checkBooleanParam(widget, 'jump')
370n/a
371n/a def test_justify(self):
372n/a widget = self.create()
373n/a self.checkEnumParam(widget, 'justify', 'left', 'right', 'center',
374n/a errmsg='bad justification "{}": must be '
375n/a 'left, right, or center')
376n/a self.checkInvalidParam(widget, 'justify', '',
377n/a errmsg='ambiguous justification "": must be '
378n/a 'left, right, or center')
379n/a
380n/a def test_orient(self):
381n/a widget = self.create()
382n/a self.assertEqual(str(widget['orient']), self.default_orient)
383n/a self.checkEnumParam(widget, 'orient', 'horizontal', 'vertical')
384n/a
385n/a def test_padx(self):
386n/a widget = self.create()
387n/a self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, -2, '12m',
388n/a conv=self._conv_pad_pixels)
389n/a
390n/a def test_pady(self):
391n/a widget = self.create()
392n/a self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, -2, '12m',
393n/a conv=self._conv_pad_pixels)
394n/a
395n/a def test_relief(self):
396n/a widget = self.create()
397n/a self.checkReliefParam(widget, 'relief')
398n/a
399n/a def test_repeatdelay(self):
400n/a widget = self.create()
401n/a self.checkIntegerParam(widget, 'repeatdelay', -500, 500)
402n/a
403n/a def test_repeatinterval(self):
404n/a widget = self.create()
405n/a self.checkIntegerParam(widget, 'repeatinterval', -500, 500)
406n/a
407n/a def test_selectbackground(self):
408n/a widget = self.create()
409n/a self.checkColorParam(widget, 'selectbackground')
410n/a
411n/a def test_selectborderwidth(self):
412n/a widget = self.create()
413n/a self.checkPixelsParam(widget, 'selectborderwidth', 1.3, 2.6, -2, '10p')
414n/a
415n/a def test_selectforeground(self):
416n/a widget = self.create()
417n/a self.checkColorParam(widget, 'selectforeground')
418n/a
419n/a def test_setgrid(self):
420n/a widget = self.create()
421n/a self.checkBooleanParam(widget, 'setgrid')
422n/a
423n/a def test_state(self):
424n/a widget = self.create()
425n/a self.checkEnumParam(widget, 'state', 'active', 'disabled', 'normal')
426n/a
427n/a def test_takefocus(self):
428n/a widget = self.create()
429n/a self.checkParams(widget, 'takefocus', '0', '1', '')
430n/a
431n/a def test_text(self):
432n/a widget = self.create()
433n/a self.checkParams(widget, 'text', '', 'any string')
434n/a
435n/a def test_textvariable(self):
436n/a widget = self.create()
437n/a var = tkinter.StringVar(self.root)
438n/a self.checkVariableParam(widget, 'textvariable', var)
439n/a
440n/a def test_troughcolor(self):
441n/a widget = self.create()
442n/a self.checkColorParam(widget, 'troughcolor')
443n/a
444n/a def test_underline(self):
445n/a widget = self.create()
446n/a self.checkIntegerParam(widget, 'underline', 0, 1, 10)
447n/a
448n/a def test_wraplength(self):
449n/a widget = self.create()
450n/a self.checkPixelsParam(widget, 'wraplength', 100)
451n/a
452n/a def test_xscrollcommand(self):
453n/a widget = self.create()
454n/a self.checkCommandParam(widget, 'xscrollcommand')
455n/a
456n/a def test_yscrollcommand(self):
457n/a widget = self.create()
458n/a self.checkCommandParam(widget, 'yscrollcommand')
459n/a
460n/a # non-standard but common options
461n/a
462n/a def test_command(self):
463n/a widget = self.create()
464n/a self.checkCommandParam(widget, 'command')
465n/a
466n/a def test_indicatoron(self):
467n/a widget = self.create()
468n/a self.checkBooleanParam(widget, 'indicatoron')
469n/a
470n/a def test_offrelief(self):
471n/a widget = self.create()
472n/a self.checkReliefParam(widget, 'offrelief')
473n/a
474n/a def test_overrelief(self):
475n/a widget = self.create()
476n/a self.checkReliefParam(widget, 'overrelief')
477n/a
478n/a def test_selectcolor(self):
479n/a widget = self.create()
480n/a self.checkColorParam(widget, 'selectcolor')
481n/a
482n/a def test_selectimage(self):
483n/a widget = self.create()
484n/a self.checkImageParam(widget, 'selectimage')
485n/a
486n/a @requires_tcl(8, 5)
487n/a def test_tristateimage(self):
488n/a widget = self.create()
489n/a self.checkImageParam(widget, 'tristateimage')
490n/a
491n/a @requires_tcl(8, 5)
492n/a def test_tristatevalue(self):
493n/a widget = self.create()
494n/a self.checkParam(widget, 'tristatevalue', 'unknowable')
495n/a
496n/a def test_variable(self):
497n/a widget = self.create()
498n/a var = tkinter.DoubleVar(self.root)
499n/a self.checkVariableParam(widget, 'variable', var)
500n/a
501n/a
502n/aclass IntegerSizeTests:
503n/a def test_height(self):
504n/a widget = self.create()
505n/a self.checkIntegerParam(widget, 'height', 100, -100, 0)
506n/a
507n/a def test_width(self):
508n/a widget = self.create()
509n/a self.checkIntegerParam(widget, 'width', 402, -402, 0)
510n/a
511n/a
512n/aclass PixelSizeTests:
513n/a def test_height(self):
514n/a widget = self.create()
515n/a self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '3c')
516n/a
517n/a def test_width(self):
518n/a widget = self.create()
519n/a self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i')
520n/a
521n/a
522n/adef add_standard_options(*source_classes):
523n/a # This decorator adds test_xxx methods from source classes for every xxx
524n/a # option in the OPTIONS class attribute if they are not defined explicitly.
525n/a def decorator(cls):
526n/a for option in cls.OPTIONS:
527n/a methodname = 'test_' + option
528n/a if not hasattr(cls, methodname):
529n/a for source_class in source_classes:
530n/a if hasattr(source_class, methodname):
531n/a setattr(cls, methodname,
532n/a getattr(source_class, methodname))
533n/a break
534n/a else:
535n/a def test(self, option=option):
536n/a widget = self.create()
537n/a widget[option]
538n/a raise AssertionError('Option "%s" is not tested in %s' %
539n/a (option, cls.__name__))
540n/a test.__name__ = methodname
541n/a setattr(cls, methodname, test)
542n/a return cls
543n/a return decorator
544n/a
545n/adef setUpModule():
546n/a if test.support.verbose:
547n/a tcl = tkinter.Tcl()
548n/a print('patchlevel =', tcl.call('info', 'patchlevel'))