做uiautomator1.0有一段时间了,一直想写点东西记录下,这样也能很好的分享给团队的新人,但是总是被自己忙的借口给delay了,今天参考了别人写的文章,加上自己在编写case过程中遇到的问题,就写了这篇文章
言归正传,那么uiautomator和现在业界里主流的一些android自动化测试框架或者技术相比有什么优缺点么?
优点:1.可以对所有操作进行自动化,操作简单;
2.不需要对被测程序进行重签名,且,可以测试所有设备上的程序,比如~某APP,比如~拨号,比如~发信息等等
3.对于控件定位,要比robotium简单一点点
缺点:1.uiautomator需要android level 16以上才可以使用,因为在level 16及以上的API里面才带有uiautomator工具
2.如果想要使用resource-id定位控件,则需要level 18及以上才可以
3.对中文支持不好(不代表不支持,第三方jar可以实现)
4.个人感觉,控件定位不如robotium那样层级分明,仅仅个人感觉,用户行为注入还是和插桩有点点区别的
正题!正题!正题!(重要的事情说三遍)
第一步、环境准备:
1.JDK(是的,你没看错,基础的android开发环境必备),以及对应的环境变量配置,不会的可以自己百度下下
2.eclispse(IDE尊崇个人意愿)
3.android SDK以及配置
注意上述三步是必须配置的,下面第4步骤,由于我们eclipse里面集成ant plugin,所以我们直接在eclipse下面ant build生成jar,可以快速实现
4.ANT(主要用于build我们的脚本,生成jar包)(可忽略)
ant的搭建主要分几步:1.下载ant安装文件并且解压安装;
2.新建系统环境变量ANT_HOME,参数值是你的ant安装目录;
3.在Path环境变量中添加ant安装目录的bin文件夹,比如我的就是C:\cod\apache-ant-1.9.6\bin
4.配置完以后,测试一下,在命令行下输入ant -version,如果显示你所安装的ant版本信息,证明环境变量配置成功
第二步、建立我们的测试工程:
一、使用Eclipse新建Java Project
二、添加依赖jar
添加android.jar(在测试工程上右键-properties-Java Build Path-add external JARs)选择SDK目录下的Android\Sdk\platforms\android-22\下面的android.jar和uiautomator.jar添加进来
三、在测试工程src文件夹中add package,然后添加一个class文件,命名随意
文件内容是这样滴:
public class MtCall extends UiAutomatorTestCase {
private ITestApi itest;
private static boolean Debug = false;
String sim1num, sim2num, assistantNum;
SocketUtil socketUtil = new SocketUtil();
@Override
protected void setUp() throws Exception {
super.setUp();
UiUtils.registerWather(getUiDevice());
itest = ITestApp.newInstance();
socketUtil.startSocket();
UiDevice.getInstance().pressHome();
ConfigUtils config = ConfigUtils.getInstance();
sim1num = config.getSim1Number();
sim2num = config.getSim2Number();
assistantNum = config.getHelpNumber();
UiUtils.takeScreenshot("setUp", Debug);
}
@Override
protected void tearDown() throws Exception {
itest.sendCommand("EndCall");
itest.finish();
super.tearDown();
socketUtil.sendMsg("sprdtest assistant client status update "+ getSerialNumber() + " true");
socketUtil.closeSocket();
UiUtils.removerWather(getUiDevice());
UiDevice.getInstance().pressHome();
UiUtils.clearBackgroundAppsForAndroidL();
}
public void test_mt() throws UiObjectNotFoundException,
InterruptedException, Exception {
// 删除SD卡通话录音
Runtime.getRuntime().exec("rm -rf /storage/sdcard0/voicecall");
// 卡1被叫接听
System.out.println("Sim1 Called Begin...");
socketUtil.sendMsg("sprdtest call " + sim1num + " 2 "
+ getSerialNumber());
if (getIncomingStatus()) {
receiveCall(sim1num);
} else {
socketUtil.sendMsg("sprdtest assistant client status update "
+ getSerialNumber() + " true");
UiUtils.Sleep(3000);
socketUtil.sendMsg("sprdtest call " + sim1num + " 2 "
+ getSerialNumber());
getIncomingStatus();
receiveCall(sim1num);
}
}
具体方法,以及一些API,后面给大家介绍
四、CMD进入\Android-sdk\tools\目录下,运行命令 android list,查看对应android版本的SDK的ID值
五、仍然在\Android-sdk\tools\目录下,运行命令:android create uitest-project -n
比如:
android create uitest-project -n Checker -t 1 -p D:\case\AndroidL\UiAutomatorAndroidL5MAPNEW
上面的name就是将来生成的jar包的名字,可以自己定义;android-sdk-ID就是上面看到的对应android版本的SDK id;path是Eclipse里刚才建立的测试工程的路径;运行命令后,将会在工程的根目录下生成build.xml文件。如果没生成,检查上面的步骤。
六、使用我们写的脚本,custom_rules.xml,右击build.xml可以编译生成jar和xml成功后,会在工程bin目录下生成对应名称的jar包
七、将jar包push到手机data/local/tmp目录下,对应的命令是:
adb push
然后使用命令行启动我们已经push进去的uiautomator脚本
adb shell uiautomator runtest
例:adb shell uiautomator runtest check.jar -c com.ct.uiTest.CheckSize
完成这一步后,手机会执行uiautomator脚本并且开始进行操作,关于uiautomator的对应api,由于今天太晚了,明天我们接着唠
---------------------------------------------------我是华丽的分割线--------------------------------------------------------------
uiautomator的基础对象:
代表设备状态。在测试中,可以通过UiDevice实例来检测设备的各种属性,例如当前的屏幕方向以及屏幕尺寸。同时还可以通过UiDevice实例来执行设备级别的操作,例如 把设备设置为横屏或者竖屏、按下Home按键等。
例:getUiDevice().pressHome(); //模拟按下home键操作
代表一个搜索UI控件的条件。如果发现多个满足条件的控件则会返回第一个控件。返回的结果为UiObject对象。在构造UiSelector的时候可以 组合使用多个属性来定位具体的控件。如果没有找到控件则会抛出 UiAutomatorObjectNotFoundException 异常
代表一个UI控件。通过UiSelector来查找UiObject。
代表控件的集合。获取UiCollection的方式和UiObject一样,通过 UiSelector查找。 UiCollection对应Android系统中的ViewGroup以及子控件。比如界面中有多个check时,我们要使用classname获取当前界面中所有的checkbox,就可以使用UICollection来接收获取到的控件集合
代表可滚动的控件。可以用UiScrollable来模拟水平或者垂直滚动的UI元素。如果需要操作的元素在屏幕外需要滚动屏幕才能看到的情况下需要使用UiScrollable
其他API参考uiautomator api文档
分享一下我所知道的一些uiautomator API
一、控件定位类:
控件定位属于android自动化中比较常用的,uiautomator可以使用resource-id,文本,index,classname(控件类型),伪xpath
通过文本定位:
例:textview = new UiObject(new UiSelector().text("user info"));
该方法通过直接查找当前界面上所有的控件来比较每个控件的text属性是否如参数值来定位控件,挺好理解的,所以就没有必要细说了。
UISelector.textContains方法
例:addNote = new UiObject(new UiSelector().textStartsWith("user"));
此方法跟以上方法类似,但是不需要输入控件的全部text信息
通过resource-id定位:
UISelector().resourceId方法
例:UiObject lb=new UiObject(new UiSelector().resourceId("com.cleanmaster.mguard:id/relativeLayoutBtns"));
resource-id可以通过android_sdk tools目录下的uiautomatorviewer工具查看
通过classname定位:
UiSelector().classname方法
例:UiCollection list=new UiObject(new UiSelector().className("android.widget.CheckBox"));
通过伪xpath定位:
UISelector类提供了一些方法根据控件在界面的XML布局中的层级关系来进行定位,但是UIAutomator又没有真正的提供类似Appium的findElementWithXpath相关的方法,所以这个位置我们叫它伪xpath,其实就是通过层级一层一层去定位控件,通常用于Listview中定位id相同的控件
例:UiObject uio=new UiObject(new UiSelector().text("Cache junk").fromParent(new UiSelector().className("android.widget.CheckBox")));
上面这段代码是一个场景
这是一个android里面常见的listview,它里面有很多的layout,可是如果我只想获取到cache junk这一条目中的checkbox,又没有id,index又不固定的情况下,怎么办呢,就使用上面那段代码,以下是UI和层级关系
那段代码的思路是,使用text定位cache junk这个UI中的唯一性控件,然后.fromParent定位到cache junk控件的父控件,就是index为1的那个RelativeLayout控件,再在RelativeLayout控件中通过classname定位这个layout中的唯一一个checkbox控件,大家可以想一下这个思路,你小儿子踢足球把我家玻璃打碎了,逃逸了,我认识你大儿子,我通过你大儿子找到你爸爸,再通过你爸爸找到小儿子,揍一顿~
刚才是一个通过孩子找父亲再找兄弟的思路,那么这个方法就是我知道你爸爸是谁,我直接通过你爸爸找到儿子
例:UiObject parentView = new UiObject(new UiSelector().className("android.view.View"));
save = parentView.getChild(new UiSelector().text("Save"));
以上就是一些比较常用的,定位控件的方法,下面是一些零散的操作类方法
·唤醒手机:getUiDevice().wakeUp();
·点击控件:UiObject huancun=new UiObject(new UiSelector().text("Cache junk"));
huancun.click();
·滑动:getUiDevice().swipe(startX, startY, endX, endY, steps)
在手机上滑动,从(startX,startY)到(endX,endY)。steps表示滑动的这个距离分为几步完成,数目越少,滑动幅度越大
·点击并等待窗口刷新:UiObject huancun=new UiObject(new UiSelector().text("Cache junk"));
huancun..clickAndWaitForNewWindow()
·长按:UiObject huancun=new UiObject(new UiSelector().text("Cache junk"));
huancun.longclick();
以上就是我所知道并且经常使用的一些方法,读完这篇博文,可能并不会让你马上写出一个非常牛逼,功能非常全面的脚本,但是初学者可以在一个点击的完成,或者成功定位到一个很复杂的控件后,多一点点成就感,以此来培养这方面的兴趣,相信将来,你终究也会是大神