Tuesday, November 27, 2012

AndroidViewClient: UiAutomator support

AndroidViewClient v2.3.1 has been released recently providing UiAutomator compatibility, when supported by the device or emulator. UiAutomator is supported since Android API 16.

This is a great improvement over previous version in two different aspects:

  • it can now be run on non-rooted devices not demanding application modification (as previous version required to use LocalViewServer)
  • the change in the backend now frees the client from port redirection, as ViewServer requests, and at the same time the performance of dumping the View tree is greatly improved
 As an introduction of this new release we will be using a simple example that demonstrates some of the new features. This example us based on the demo application AndroidSampleUi.apk.

This example demonstrates:

  • automatic device connection, handling command line parameters if present
  • automatic View tree dump
  • finding Views using regular expressions or text
  • touching found Views
As a precondition to run this example, install and run AndroidSampleUI.


Zoom buttons let you increase or decrease the margins and consequently move the toggle buttons to demonstrate that they will be found whatever their coordinates are.

#! /usr/bin/env monkeyrunner
'''
Copyright (C) 2012  Diego Torres Milano
Created on Aug 31, 2012

@author: diego
'''


import re
import sys
import os

# This must be imported before MonkeyRunner and MonkeyDevice,
# otherwise the import fails.
# PyDev sets PYTHONPATH, use it
try:
    for p in os.environ['PYTHONPATH'].split(':'):
       if not p in sys.path:
          sys.path.append(p)
except:
    pass

try:
    sys.path.append(os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
except:
    pass
from com.dtmilano.android.viewclient import ViewClient, ViewNotFoundException

vc = ViewClient(*ViewClient.connectToDeviceOrExit())

# Find the 3 toggle buttons, because the first 2 change their text if they are selected
# we use a regex to find them.
# Once found, we touch them changing their state
for t in [re.compile('Button 1 .*'), re.compile('Button 2 .*'), 'Button with ID']:
    try:
        vc.findViewWithTextOrRaise(t).touch()
    except ViewNotFoundException:
        print >>sys.stderr, "Couldn't find button with text=", t

Once this script is run, ViewClient will find a device, which can be specified using its serial number in the command line invoking the script, connects to, automatically dump the tree and then use regular expressions to find two of the ToggleButtons because we couldn't use a fixed text because it changes when the button is clicked. If, for some reason the Button is not found, perhaps because it was move outside the screen using Zoom buttons, a message is printed.

This screenshot show the state of the Buttons after the script has run.



More articles and examples will be coming soon, but I didn't want to miss the opportunity to introduce this new version. One of the most remarkably advantages over plain UiAutomator is the  simplification of the script or test creation and the expressiveness gain of using Python instead of Java.

dump.py

dump.py is also present in AndroidViewClient examples. It now supports several command line options now

usage: dump.py [-u|--uniqueId] [-x|--position] [-d|--content-description] [serialno]

so we can use it to verify the content of the screen. If everything went well running

dump.py --content-description

will show the View tree including also the content descriptions, as given by the following dump


android.widget.FrameLayout id/no_id/1  
   android.widget.LinearLayout id/no_id/2  
      android.widget.FrameLayout id/no_id/3  
         android.view.View id/no_id/4  
            android.widget.FrameLayout id/no_id/5  
               android.widget.ImageView id/no_id/6  
            android.widget.LinearLayout id/no_id/7  
               android.widget.LinearLayout id/no_id/8  
                  android.widget.TextView id/no_id/9 Sample UI v2.0 
      android.widget.FrameLayout id/no_id/10  
         android.widget.RelativeLayout id/no_id/11  
            android.widget.Button id/no_id/12 Show Dialog show_dialog
            android.widget.LinearLayout id/no_id/13  
               android.widget.TextView id/no_id/14  
               android.widget.ToggleButton id/no_id/15 Button 1 OFF button_1
               android.widget.TextView id/no_id/16 v=(75.0,82.0) lw=(115,272) ls=(115,272) wxh=(290,72) margin=(40,80) button_1_info
               android.widget.ToggleButton id/no_id/17 Button 2 OFF button_2
               android.widget.TextView id/no_id/18 v=(75.0,273.0) lw=(115,463) ls=(115,463) wxh=(290,72) margin=(40,80) button_2_info
               android.widget.ToggleButton id/no_id/19 Button with ID button_with_id
            android.widget.ZoomControls id/no_id/20  zoom
               android.widget.ZoomButton id/no_id/21  
               android.widget.ZoomButton id/no_id/22  


UPDATE:
Changed linked version to AndroidViewClient 2.3.1 as some latest commits were not in version 2.3 as found by Durairaj.
Post a Comment