首先提供uiautomator的官方网页:
http://developer.android.com/tools/help/uiautomator/index.html
uiautomator 测试案例(Test case)需要继承至UiAutomatorTestCase 类。而UiAutomatorTestCase 类继承至junit.framework.TestCase类,所以可以用JUnit的Assert类来比较测试结果。
uiautomator API
uiautomator API在 uiautomator.jar 文件中。这些API分别如下:
UiDevice
代表设备状态。在测试中,可以通过UiDevice实例来检测设备的各种属性,例如当前的屏幕方向以及屏幕尺寸。同时还可以通过UiDevice实例来执行设备级别的操作,例如 把设备设置为横屏或者竖屏、按下Home按键等。
摘要:
函数返回值 | 函数体 | 说明 | 实例 |
boolean | click(int x, int y) | 模拟用户在指定位置点击 | mdevice.click(200, 300) 点击屏幕的200,300坐标处 |
String | getCurrentActivityName() | 获得的是应用程序在桌面上显示的名字 | 例如,在qq首页得到的是“QQ”,在微信登录页得到的是“微信”,注意,这个得到的不是Activity的名字 |
String | getCurrentPackageName() | 获得当前显示的应用程序的包名 | 例如,在微信启动的时候,获得的是“com.tencent.mm” |
int | getDisplayHeight() | 获得当前设备的屏幕分辨率的高 | 例如,我的手机1920*1080,得到的是 1920 |
int | getDisplayWighth() | 获得当前设备的屏幕分辨率的宽 | 例如,我的手机1920*1080,得到的是 1080 |
boolean | isScreenOn() | 判断手机当前是否灭屏 | 当手机灭屏的时候,得到是“false”,手机亮屏,得到的是“true” |
void | wakeUp() | 点亮当前屏幕 | 调用后,相当于按下了电源键,如果手机设置了滑动锁屏,滑动锁屏还是在的,不会自动解开 |
boolean | pressBack() | 点击back键 | |
boolean | pressHome() | 点击home键 | |
boolean | pressMenu() | 点击menu键 | |
boolean | pressKeyCode(int keyCode) | 利用keycode值模拟一次按下事件 | 例如,需要按下数字1 数字1的keycode是 KEYCODE_NUMPAD_1,更多keycode可以在 http://developer.android.com/intl/zh-cn/reference/android/view/KeyEvent.html 进行查询 |
boolean | swipe(int startX, int startY, int endX, int endY, int steps) | 用指定的步长,从A点滑动B点 | 例如,需要从(10, 10)点用两步滑动到(100, 200)点,则需要mdevice.swipe(10, 10, 100, 200, 2) |
boolean | takeScreenshot(File storePath) | 截取当前屏幕,保存到文件 | 例如,File files = new File("/sdcard/res.jpg"); mdevice.takeScreenshot(files); 即可将截图保存到sd卡中了。 |
UiSelector
代表一个搜索UI控件的条件。如果发现多个满足条件的控件则会返回第一个控件。返回的结果为UiObject对象。在构造UiSelector的时候可以组合使用多个属性来定位具体的控件。如果没有找到控件则会抛出 UiAutomatorObjectNotFoundException 异常。还可以使用childSelector()函数来嵌套UiSelector 对象。
例如,下面的代码演示了如何在当前界面中查找第一个ListView中的带有文本属性为Apps的子控件。
Java
1 2 3 |
UiObject appItem = new UiObject(new UiSelector().className("android.widget.ListView").instance(1).childSelector(new UiSelector().text("Apps"))); |
例如,还可以限制仅仅查找特定类型的控件。如下代码只查找文本为“Cancel”和“OK”的android.widget.Button类型控件。
Java
1 2 3 4 |
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel") .className("android.widget.Button")); UiObject okButton = new UiObject(new UiSelector().text("OK") .className("android.widget.Button")); |
1、根据text构造:
函数返回值 | 函数体 | 说明 | 用法 |
UiSelector | text(String text) | 根据“控件text属性的内容”构造出UiSelector对象 | 例如,一个控件text的值是“发现”,UiSelector s = new UiSelector().text("发现"); |
UiSelector | textContains(String text) | 根据“控件text属性包含的内容”构造出UiSelector对象 | 同上例子:UiSelector s = new UiSelector().textContains("现"); |
UiSelector | textMatches(String regex) | 根据“控件text属性正则表达式的内容”构造出UiSelector对象 | 正则表达式语法参考网上资料即可。 |
UiSelector | textStartsWith(String text) | 根据“控件text属性开始的内容”构造出UiSelector对象 | 同上例子:UiSelector s = new UiSelector().textStartsWith("发"); |
比较常用,准确度也比较高,中文查找的时候,如果遇到 “UiOjbectNotFoundException” 的时候,记得把项目的编码格式改为utf-8。
2、根据description构造:
UiSelector | description(String desc) | 根据“控件content-desc属性的内容”构造出UiSelector对象 |
UiSelector | descriptionContains(String desc) | 包含** |
UiSelector | descriptionMatches(String regex) | 正则 |
UiSelector | descriptionStartsWith(String desc) | 以**开始 |
同text的用法基本一致,也是比较靠谱的一种方式。
3、根据资源id:
UiSelector | resourceId(String id) | 根据资源id获取对象,例如:UiSelector s = new UiSelector().resourceId("com.tencent.mm:id/b8m") |
UiSelector | resourceIdMatches(String regex) | 根据资源id的正则表达式获取对象 |
4、根据类:
UiSelector className(String className):
根据控件的类名来找到UiSelector对象。
但是呢?因为一般Android布局的时候,同样的控件类名都是一样的。
因此我在微信的登录界面调用: UiSelector s = new UiSelector().className("android.widget.TextView") 这句话,它得到的就是我左上开始算第一个class名称为“android.widget.TextView”的控件。
UiSelector instance (int instance):
上面提到的假如我们想获取屏幕上电话号码的那个TextView使用这样方法,就可以使用instance:
UiSelector s = new UiSelector().className("android.widget.TextView").instance(1);
UiSelector index(int index):
用法和上面的instance差不多,谷歌的原文说这个方法是unreliable的,推荐使用instance方法。
UiSelector childSelector(UiSelector selector):
有的时候假如子控件不好获得,而其父控件比较好获得的时候,我们通常采用这样的方式,例如下面:
我们目前选中的是LinearLayout,这个Android中的一种布局,它的里面嵌套了两个控件,一个是ImageView,另一个是EditText。这们这里就通过LinearLayout这个控件找到它的子控件。
很明显,父控件id已经给定。我们先得到父控件:UiSelector s_p = new UiSelector().resourceId("com.tencent.mm:id/axj");
其次 UiSelector s_c= s_p.childSelector( new UiSelector().className("android.widget.EditText") );
在它的父控件的childSelector方法中传入一个带有一定特征的UiSelector对象,即可得到子控件,这里 s_c 就是输入框的UiSelector对象。
UiSelector fromParent(UiSelector selector):
有的时候父控件也不好获得,而是同级的控件(同属一个parent)比较好获取,那么使用这样方法,还拿上面的举例:
我们先得到EditText的UiSelector对象:UiSelector s1 = new UiSelector().resourceId("com.tencent.mm:id/axc");
得到和它同样一个父控件的ImageView的UiSelector对象:UiSelector s2 = fromParent( new UiSelector().className("android.widget.ImageView") );
5、根据特有属性:
UiSelector | checked(boolean val) | 根据是否可check来构造出UiSelector对象 |
UiSelector | chickable(boolean val) | |
UiSelector | enabled(boolean val) | |
UiSelector | focusable(boolean val) | |
UiSelector | longClickable(boolean val) | |
UiSelector | scrollable(boolean val) | |
UiSelector | selected(boolean val) |
举个简单的例如,假如当前的界面,只有一个checkbox是勾选状态,你就可以这样得到:UiSelector s2 = new UiSelector().checked(true)
UiObject
代表一个UI控件。通过UiSelector来查找UiObject。
如下示例代码演示了如何查找当前显示界面中的取消按钮和确认按钮:
Java
1 2 |
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel")); UiObject okButton = new UiObject(new UiSelector().text("OK")); |
查找到的UiObject实例可以在其他测试代码中重用。需要注意的是:每次使用UiObject做操作的时候uiautomator 都会在当前屏幕重新查找该控件。
如下代码uiautomator 工具在当前界面查找文本内容为“OK”的控件。如果存在并且可用则模拟用户点击该控件。
Java
1 2 3 4 |
if(okButton.exists() && okButton.isEnabled()) { okButton.click(); } |
摘要:
返回值 |
函数 |
void |
ClearTextField() |
boolean |
click() |
boolean |
clickAndWaiForNewWindow(long timeout) |
boolean |
clickAndWaiForNewWindow() |
boolean |
clickBottomRight() |
boolean |
clickTopLeft() |
boolean |
exists() |
Rect |
getBounds() |
UiObject |
getChild(UiSelector selector) |
int |
getChildCount() |
String |
getContentDescription() |
UiObject |
getFromParent(UiSelector selector) |
String |
getPackageName() |
final UiSelector |
getSelector() |
String |
getText() |
Rect |
getVisibleBounds() |
boolean |
isCheckable() |
boolean |
isChecked() |
boolean |
isClickable() |
boolean |
isEnabled() |
boolean |
isFocusable() |
boolean |
isFocused() |
boolean |
isLongClickable() |
boolean |
isScrollable() |
boolean |
isSelected() |
boolean |
longClick() |
boolean |
longClickBottomRight() |
boolean |
longClickTopLeft() |
boolean |
setText(String text) |
boolean |
swipeDown(int steps) |
boolean |
swipeLeft(int steps) |
boolean |
swipeRight(int steps) |
boolean |
swipeUp(int steps) |
boolean |
waitForExists(long timeout) |
boolean |
waitUntilGone(long timeout) |
UiCollection
代表控件的集合。获取UiCollection的方式和UiObject一样,通过 UiSelector查找。 UiCollection对应Android系统中的ViewGroup以及子控件。
如下代码演示如何通过UiSelector来获取包含视频集合的UiCollection。
Java
1 2 |
UiCollection videos = new UiCollection(new UiSelector().className("android.widget.FrameLayout")); |
如果每个视频是放到LinearLayout中的,则可以通过如下方式获取视频的数目:
Java
1 2 |
int count = videos.getChildCount(new UiSelector() .className("android.widget.LinearLayout")); |
如果需要查找标签为“Cute Baby Laughing”的视频,并点击。则可以通过如下方式:
Java
1 2 3 |
UiObject video = videos.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "Cute Baby Laughing"); video.click(); |
同样还可以模拟其他用户操作。例如,模拟选择视频的操作如下:
Java
1 2 3 |
UiObject checkBox = video.getChild(new UiSelector().className("android.widget.Checkbox")); if(!checkBox.isSelected()) checkbox.click(); |
UiScrollable
代表可滚动的控件。可以用UiScrollable来模拟水平或者垂直滚动的UI元素。如果需要操作的元素在屏幕外需要滚动屏幕才能看到的情况下需要使用UiScrollable。
例如,下面的代码显示了如何模拟滚动到“Settings ”菜单并点击“About tablet”菜单的操作。
Java
1 2 3 4 5 |
UiScrollable settingsItem = new UiScrollable(new UiSelector().className("android.widget.ListView")); UiObject about = settingsItem.getChildByText(new UiSelector().className("android.widget.LinearLayout"), "About tablet"); about.click() |
其他API参考uiautomator api文档。