选择原因
- API接口丰富,包括 android 所有事件。不依赖屏幕坐标控制。
- 对比Rubotium,无需新建测试项目。无需为了测试多安装个apk,而且不必进入 adb shell 环境调起测试程序。
简单例子
亮屏进入测试app界面点击按钮的简单操作
public class MatorTest extends UiAutomatorTestCase{
public void test() throws RemoteException, UiObjectNotFoundException {
System.out.println("\n \n -- MyLogInfo start --\n \n");
UiDevice uiDevice = getUiDevice();
System.out.println(" 亮屏,上滑解锁,左滑进入第二屏 ");
uiDevice.wakeUp();
sleep(500);
uiDevice.swipe(uiDevice.getDisplayWidth() / 2, uiDevice.getDisplayHeight() - 20, uiDevice.getDisplayWidth() / 2, uiDevice.getDisplayHeight() / 2, 5);
sleep(500);
uiDevice.pressHome();
sleep(1000);
uiDevice.swipe(uiDevice.getDisplayWidth() - 20, 100, uiDevice.getDisplayWidth() / 2, 100, 10);
sleep(500);
System.out.println(" 进入AutomatorTest ");
UiObject myAppButton = new UiObject(new UiSelector().text("AutomatorTest"));
myAppButton.clickAndWaitForNewWindow();
System.out.println(" 进入软件后的操作 ");
UiObject btn1 = new UiObject(new UiSelector().className(Button.class).text("button1"));
btn1.click();
UiObject btn2 = new UiObject(new UiSelector().className(Button.class).text("button2"));
btn2.click();
UiObject btn3 = new UiObject(new UiSelector().className(Button.class).text("button3"));
btn3.click();
UiObject btnJump = new UiObject(new UiSelector().className(Button.class).text("跳转"));
btnJump.click();
sleep(300);
System.out.println(" 系统按键操作 ");
uiDevice.pressBack();
sleep(300);
uiDevice.pressHome();
sleep(300);
System.out.println("\n \n -- MyLogInfo end -- \n \n");
}
}
uiautomatorviewer
启动
位于 sdk\tools\uiautomatorviewer.bat
。命令行打开进入界面
操作
分别对应左上角的四个按钮,从左到右的顺序
- 打开
- Device ScreenShot( uiautomator dump)
一般层次截图,将所有的层次展示 - Device ScreenShot with Compressed Hierarchy(uiautomator dump –compressed)
压缩层次截图。多个层次压缩为一层展示 - 保存
当当前分析的结果保存,两个文件:png、uix
批处理脚本。再也不用手动编译、执行测试脚本
自动完成测试脚本所有过程(构建、编译、Push、运行)如下:
- cd/d d:\es\sdk\tools\
- android create uitest-project -n test -t 9 -p D:\AndroidWorkspace\AutomatorTest
- cd/d d:\AndroidWorkspace\AutomatorTest
- ant build
- adb push D:\AndroidWorkspace\AutomatorTest\bin\test.jar data/local/tmp
- adb shell uiautomator runtest test.jar -c com.example.automatortest.test.MatorTest
【1、2】 利用 android.bat 生成脚本配置文件:build.xml。位于工程的主目录下
【3、4】 ANT 工具将 build.xml 配置转换为 jar 测试脚本
【5】 将 jar 测试脚本推送到手机目录的 data/local/tmp
【6】 使用 uiautomator 工具运行手机目录中存在的 test.jar 文件去去测试指定工程
若每次使用都需要手动输入编译语句,不同的文件夹切换。会很不方便,白白浪费时间。变写了自动编译脚本。不同的工程变化下目录文件就可以了。
windows -> .bat(.cmd)
cmd /k "cd/d d:\es\sdk\tools\ && android create uitest-project -n test -t 9 -p D:\AndroidWorkspace\AutomatorTest && cd/d d:\AndroidWorkspace\AutomatorTest && ant build && adb push D:\AndroidWorkspace\AutomatorTest\bin\test.jar data/local/tmp && adb shell uiautomator runtest test.jar -c com.example.automatortest.test.MatorTest"
将上述代码复制到txt文本中将后缀名改为.bat(.cmd),双击运行即可。需要手动修改各个部分路径指向。
附录
UiAutomator 接口
对象:UiDevice
对设备进行的操作
坐标参数
- boolean click(int x, int y)
- 在坐标点(x, y)点击
- int getDisplayHeight()
- 获取屏幕高度
- int getDisplayWidth()
- 获取屏幕宽度
- Point getDisplaySizeDp()
- 获取显示尺寸大小
系统信息
- void getCurrentPackageName()
- 获取当前界面包名
- void getCurrentActivityName()
- 获取当前界面Activity
- void dumpWindowHierarchy(fileName)
- dump当前布局文件到/data/local/tmp/目录
滑动、拖拽
- boolean drag(startX, startY, endX, endY, steps)
- 拖拽坐标处对象到另一个坐标
- boolean swipe(segments, segmentSteps)
- 在Points[]中以segmentSteps滑动
- boolean swipe(startX, startY, endX, endY, steps)
- 通过坐标滑动
系统按键
- void wakeUp()
- 按电源键亮屏
- void sleep()
- 按电源键灭屏
- boolean isScreenOn()
- 亮屏状态
- void setOrientationLeft()
- 禁用传感器,并左旋屏幕,固定
- void setOrientationNatural()
- 禁用传感器,恢复默认屏幕方向,固定
- void setOrientationRight()
- 禁用传感器,并右旋屏幕,固定
- void unfreezeRotation()
- 启用传感器,并允许旋转
- boolean isNaturalOrientation()
- 检测是否处于默认旋转状态
- void getDisplayRotation()
- 返回当前旋转状态,0、1、、2、3分别代表0、90、180、270度旋转
- void freezeRotation()
- 禁用传感器,并冻结当前状态
- boolean takeScreenshot(storePath)
- 当前窗口截图、1.0f缩放、90%质量保存在storePath
- void takeScreenshot(storePath, scale, quality)
- 同上,但指定缩放和压缩比率
- void openNotification()
- 打开通知栏
- void openQuickSettings()
- 打开快速设置
等待窗口
- void waitForIdle()
- 等待当前窗口处于空闲状态、默认10s
- void waitForIdle(long timeout)
- 自定义超时等待当前窗口处于空闲状态
- boolean waitForWindowUpdate(packageName, timeout)
- 等待窗口内容更新
对象:UiSelector
UI控件搜索,通过条件、属性控件。定位若多个符合条件的默认返回第一个UiObject。也可以instance()指定第几个
通过 text、description 属性定位
- UiSelector text(text)
- 通过text完全定位
- UiSelector textContains(text)
- 通过text包含定位
- UiSelector textMatches(regex)
- 通过text正则定位
- UiSelector textStartsWith(text)
- 通过text起始文字定位
- UiSelector description(text)
- 通过text完全定位
- UiSelector descriptionContains(text)
- 通过description包含定位
- UiSelector descriptionMatches(regex)
- 通过description正则定位
- UiSelector descriptionStartsWith(text)
- 通过description起始文字定位
通过resourceId定位
- UiSelector resourceId(id)
- 通过resourceId定位
- UiSelector resourceIdMatches(regex)
- 通过resourceId正则定位
通过class、package定位
- UiSelector className(className)
- 通过class定位
- UiSelector classNameMatches(regex)
- 通过class正则定位
- UiSelector packageName(name)
- 通过package定位
- UiSelector packageNameMatches(regex)
- 通过package正则定位
通过index、instance定位
- UiSelector index(index)
- 通过index定位
- UiSelector instance(instance)
- 通过instance定位
通过其他属性定位
- UiSelector enabled(val)
- 通过enabled属性定位
Android 的 View 对象的所有属性都可以使用,这里不再列举。
对象:UIObject
代表一个控件,注意:每次使用 UiObject 对象时,都会在当前屏幕重新查找。
Android 中 View 的常用操作都有,列举重要的几个
状态和属性
- boolean setText(text)
- 设置内容为text
-boolean clearTextField()
- 清除文本
- boolean isCheckable()
- 获取对象checkable状态
- boolean exists()
- 对象是否存在
- boolean waitForExists(timeout)
- 等待对象出现
- boolean waitUntilGone(timeout)
- 等待对象消失
- Rect getBounds()
- 获取对象矩形范围
- int getChildCount()
- 获取子View数量
手势操作
- boolean click()
- 点击对象。可以指定位置,如右下角:clickBottomRight() ...
- boolean longClick()
- 长按对象。可以指定位置,如右下角:longClickBottomRight() ...
- boolean dragTo(destObj, steps)
- 以steps拖动对象到destObj
- boolean dragTo(destX, destY, steps)
- 以steps拖动对象到坐标
- boolean swipeTop(steps)
- 向上拖动。也可以是其他方向。swipeRight() ...
- boolean clickAndWaitForNewWindow()
- 点击对象并等待新窗口出现。也可以加入延时时间。clickAndWaitForNewWindow(timeout)
- boolean performMultiPointerGesture(touches)
- 执行单指手势
- boolean performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps)
- 执行双指手势
- boolean pinchIn(percent, steps)
- 双指向内收缩
- boolean pinchOut(percent, steps)
- 双指向外张开
对象:UiCollection
代表控件集合,相当于ViewGroup和其子控件,使用UiSelector查找
继承 UiObject 对象,有它所有的方法
- int getChildCount()
- 获取所有子元素数量
- int getChildCount(childPattern)
- 获取所有子元素中符合 UiSelector 条件的子元素数量
- UiObject getChild(childPattern)
- 根据 UiSelector 查找子元素
- UiObject getChildByDescription(childPattern, text)
- 默认滚动,根据 UiSelector、description text 条件查找子元素
- UiObject getChildByInstance(childPattern, instance)
- 默认滚动,根据 UiSelector、instance 条件查找子元素
- UiObject getChildByText(childPattern, text)
- 默认滚动,根据 UiSelector、text 条件查找子元素
对象:UiScrollable
继承了 UiCollection 所有方法,还加上了滚动的处理
滑动
- boolean setAsHorizontalList()
- 设置水平滚动,步长为5。垂直滚动:setAsVerticalList()
- boolean flingForward()
- 快速向前滑动。向后flingBackward()。
- boolean flingToBeginning(maxSwipes)
- 不超过maxSwipes向前滑动。
- boolean scrollBackward(steps)
- scroll使用和fling相识。可以指定指定步长。
- boolean scrollIntoView(selector)
- 滚动到条件元素所处的位置
- boolean scrollTextIntoView(text)
- 滚动到文本对象所处的位置
- boolean scrollIntoView(obj)
- 滚动到obj所处的位置
属性获取、设置
- boolean getMaxSearchSwipes()
- 获取最大可扫动次数、默认30。设置:setMaxSearchSwipes(swipes)
- double getSwipeDeadZonePercentage()
- 获取滑动无效区域(到顶部的百分比)。设置:setSwipeDeadZonePercentage(swipeDeadZonePercentage)
- boolean getChildByDescription(childPattern, text, allowScrollSearch)
- 是否允许滚动,查找childPattern UiSelector所对应的text子元素
对象:UiWatcher
Interface,用于处理脚本执行过程中遇到非预想的步骤
- boolean checkForCondition()
- 条件检查回调