Testing tkinter application Testing tkinter application tkinter tkinter

Testing tkinter application


I don't know much about unittest but I found a workaround to close popup dialogs like showinfo during the tests. The idea is to use keyboard event to invoke the button of the dialog. But since the app is waiting for the user to close the popup dialog, we need to schedule in advance the keyboard event using after:

self.root.after(100, self.root.event_generate('<Return>'))v.button.invoke()

Full example

import tkinterfrom tkinter import messageboximport unittestclass MyGUI(tkinter.Frame):    def __init__(self, master, **kw):        tkinter.Frame.__init__(self, master, **kw)        self.info_button = tkinter.Button(self, command=self.info_cmd, text='Info')        self.info_button.pack()        self.quit_button = tkinter.Button(self, command=self.quit_cmd, text='Quit')        self.quit_button.pack()    def info_cmd(self):        messagebox.showinfo('Info', master=self)    def quit_cmd(self):        confirm = messagebox.askokcancel('Quit?', master=self)        if confirm:            self.destroy()class TKinterTestCase(unittest.TestCase):    def setUp(self):        self.root = tkinter.Tk()        self.root.bind('<Key>', lambda e: print(self.root, e.keysym))    def tearDown(self):        if self.root:            self.root.destroy()    def test_enter(self):        v = MyGUI(self.root)        v.pack()        self.root.update_idletasks()        # info        v.after(100, lambda: self.root.event_generate('<Return>'))        v.info_button.invoke()        # quit        def cancel():            self.root.event_generate('<Tab>')            self.root.event_generate('<Return>')        v.after(100, cancel)        v.quit_button.invoke()        self.assertTrue(v.winfo_ismapped())            v.after(100, lambda: self.root.event_generate('<Return>'))        v.quit_button.invoke()        with self.assertRaises(tkinter.TclError):            v.winfo_ismapped()if __name__ == "__main__":    unittest.main()