Enumerate all elements in Selenium Python bindings for Appium
I still would like a way to introspect the Selenium interface from Python. But I have found a workable way to get a clear image of how the app is laid out, and it's pretty easy to then figure out how to write the Selenium tests.
First, get your app running, either on a real device connected to your Android development computer or in an emulator. Basically if you run adb devices
you want to see a single device, the one running your app. Next, run the uiautomatorviewer
tool, and then click on the Device Screenshot
toolbar icon. (There are only two toolbar icons: the first is the Open
icon and looks like a file folder, and the one you want looks like a stack of mobile phones.)
Once you have done that, an image of your app appears, with a screenshot on the left, and a browsable tree outline on the right. The outline shows all the controls of the app, along with their text labels if any, and other information (such as whether the clickable
property is true
or false
for that control).
One warning: the controls are shown numbered, but in the Selenium bindings, the numbers might not be the same. On the ApiDemos
example app, the Graphics
button has index number 4 as it is the fifth button, but to access it by its position I had to use index 5. Index 0 was a non-clickable object holding the text "API Demos", in a different FrameLayout
object making up the header for the screen.
So, I was able to make this change to the android.py
script:
#elem = driver.find_element_by_name('Graphics')elem = driver.find_elements_by_tag_name('TextView')[5]
Comment out the driver.find_element_by_name()
call, and instead find the sixth TextView
in the entire app. That's not best practice but it shows that the uiautomationviewer
results do let me view the stuff I need to know about the controls.
Now I know enough to do a little bit of introspection:
for elem in driver.find_elements_by_tag_name('TextView'): if elem.text == "Graphics": breakelse: print("Could not find desired item")
This isn't better than just calling driver.find_element_by_name()
but it shows that I am on the right track.
uiautomatorviewer
is a practical solution to my problem. If you have a pure-Python one please let me know about it.