2

I want to get into GUI automation in order to run tests on my own program. The Program I want to test is written in Python and uses Tkinter for the GUI. The testing code though does not necessarily have to be in python, CPP would also be alright. I've done a bit of research and I am already facing a problem.

From my research, I have found that "Windows Application Driver" is a free way to test GUI. there's also "WinAppDriver UI Recorder" which seems convenient to use with it. Additionally the `Inspect.exe' program from (In my case) "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86" is useful for getting information about the GUI elements.

Assuming I have a small python code like this (only for testing):

from Tkinter import *
import ttk

class Test():
    def __init__(self):
        self.root = Tk()
        self.root.geometry("250x100")
        self.text = StringVar()
        self.text.set("Original Text")
        self.buttonA = Button(self.root, textvariable=self.text)
        self.buttonA.configure(text="test")

        self.buttonB = Button(self.root,
                                text="Click to change text",
                                command=self.changeText
                              )
        self.buttonA.pack(side=LEFT)
        self.buttonB.pack(side=RIGHT)
        self.root.mainloop()

    def changeText(self):
        self.text.set("Updated Text")

app=Test()

When running the code and inspecting buttonB with Inspect.exe the name I get as a result is "" (empty). what way is there to change that name to something informational and useful like in the calculator example, where the '7' button's name is "Seven". Which then is used in the tester like this:

self.driver.find_element_by_name("Seven").click()

which should look like this:

self.driver.find_element_by_name("buttonB").click()

for example in my case.

Avi
  • 3,075
  • 8
  • 17
  • 27
Royi Levy
  • 135
  • 7

1 Answers1

0

You can name tkinter widgets like:

self.buttonA = Button(self.root, textvariable=self.text,name = 'buttonA')

if WinAppDriver is not able to find tkinter widgets named this way. You can modify your code to invoke buttons (and get "hold" of other UI widgets) in a way that mimic UI automations frameworks:

I modified your sample to show how this can be done

from Tkinter import *
import ttk

def _widgets_by_name(parent,name,widgets):
    if not parent.winfo_children():
        if name == parent.winfo_name() :
            widgets.append(parent)
    else:
        for child in parent.winfo_children():
            _widgets_by_name(child,name,widgets)
            
def find_widget_by_name(parent,name):
    ''' ui automation function that can find a widget in an application/hierarchy of widgets by its name '''
    widgets = []
    _widgets_by_name(parent,name,widgets)
    if len(widgets) == 0:
        raise Exception(f'no widget named {name} found')
    elif len(widgets) >1:
        raise Exception(f'multiple widget named {name} found')
    return (widgets[0])


class Test():
    def __init__(self):
        self.root = Tk()
        self.root.geometry("250x100")
        self.text = StringVar()
        self.text.set("Original Text")
        self.buttonA = Button(self.root, textvariable=self.text,name = 'button-a')
        self.buttonA.configure(text="test")

        self.buttonB = Button(self.root,
                                text="Click to change text",
                                command=self.changeText,
                                name = 'button-b'
                              )
        self.buttonA.pack(side=LEFT)
        self.buttonB.pack(side=RIGHT)
        # self.root.mainloop() do not start the main loop for testing purpose
        # can still be started outside of  __init__ for normal operation 

    def changeText(self):
        self.text.set("Updated Text")
    
app=Test()

# test the app step by step
# find one of the buttons and invoke it
find_widget_by_name(app.root,'button-b').invoke()
app.root.update() # replace the app mainloop: run the UI refresh once.

assert app.text.get() == "Updated Text"
Jean-Marc Volle
  • 2,374
  • 1
  • 8
  • 16
  • I tried nearly everything that I could find on the internet that had something to do with naming tkinter widgets and non helped identifying them in WinAppDriver. – Royi Levy Aug 26 '20 at 10:04