本文主要介绍了一个可以执行安卓自动化测试的方法,使用adb命令调试手机。通过adb命令获取手机界面元素,发送动作指令给手机。
关键词:安卓 adb 自动化
1. 引言
Android系统已经占据智能移动设备市场80%以上的份额,所以相应的对于app的测试也尤为重要,而自动化测试又是一个效率高、及其节省人力的方法。现在市场上的测试框架用的比较多的是Appium。虽然Appium框架功能相对比较齐全,但是Appium的框架比较重,相关的文档指导比较少,所以使用起来,学习成本也高。本文所描述框架,主要是简化测试框架、提高执行效率。
2. 关于adb的基础
Android 调试桥 (adb) 是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试应用,并提供对 Unix shell(可用来在模拟器或连接的设备上运行各种命令)的访问。该工具作为一个客户端-服务器程序,包括三个组件:
客户端,该组件发送命令。客户端在开发计算机上运行。您可以通过发出 adb 命令从命令行终端调用客户端。
后台程序,该组件在设备上运行命令。后台程序在每个模拟器或设备实例上作为后台进程运行。
服务器,该组件管理客户端和后台程序之间的通信。服务器在开发计算机上作为后台进程运行。
3. 基础adb命令的介绍
1) 启动app
使用命令:adb shell am start (Intent可以是显示的指向app的launcher activity,例如天猫的launcher activity为:com.tmall.wireless/com.tmall.wireless.splash.TMSplashActivity),启动app。
获取界面元素
使用命令:adb -s shell uiautomator dump /sdcard/uidump.xml,dump出当前UI布局树,再解析xml,通过指定常见的 id, text, xpath 等等获取节点的坐标信息;拿到元素坐标,我们就可以进行下一步操作了。
发送动作指令
使用命令:adb shell input text (Text是输入文本内容),发送文本,前提是输入光标,已经在输入框激活。
使用命令:adb shell input tap (x,y分别为点击坐标X、Y轴),发送点击手机指令。
使用命令:adb shell input swipe (x1、y1、x2、y2分别为起始坐标和目的地坐标),发送滑动手机指令
使用命令:adb shell input keyevent (keycode为安卓手机按键指令,例如menu键是1,home键是3,back键是4)
截屏
使用命令:adb shell screencap ( absolute path是截图文件的绝对路径,例如:/sdcard/screen.png)
调试设备和开发PC之间拷贝文件
使用命令:adb push (host file是PC上需要拷贝的文件路径,device path是要拷贝到手机的目录),拷贝本地文件到调试设备中
使用命令:adb pull (device file是手机上需要拷贝的文件路径,host path是要拷贝到pc的目录),从调试设备中拷贝文件到本地
6)安装安卓App
使用命令:adb install (apk path是apk文件的绝对路径)
4. 自动化框架
本框架主要实现安卓手机的点击、输入、滑动、返回、home等功能,并且基于此框架的代码是运行在连接安卓手机的PC上,类似Appium,但是由于Appium不仅仅支持安卓app,还支持iOS app、windows app,显得过于庞大,导致运行速度很慢。
此框架只支持测试安卓app,是基于adb命令功能的封装,在执行效率上有了很大提升,详细测试流程依照下面流程图。
1)寻找目标控件
控件属性包含:text、resource-id、class、package、content-desc、checkable、checked、clickable、enable、focusable、focused、scrollable、long-clickable、password、selected、bounds。寻找的条件可以是上面列出属性的其中一个,或者多个组合。用java代码举例:
Map condition = new HashMap();
condition.put('text', 'valueText');
condition.put('resource-id', 'valueResourceid');
condition.put('content-desc', 'valueContentDesc');
根据条件寻找控件,这里首先把手机界面的结构dump出来,在进行XML解析,然后再逐个和寻找目标条件比对。用java代码举例:
public void getElement(Element element, int level, String currentNode) {
Iterator iter = condition.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String)entry.getKey();
String val = (String)entry.getValue();
if (!element.attributeValue(key).equals(val)) {
break;
}
targetElement = elemen;
}
List elements = element.elements();
Iterator it = elements.iterator();
level++;
while (it.hasNext()) {
Element elem = (Element) it.next();
getNodes(elem, level, currentNode);
}
}
2)点击目标控件,输入文本,返回、home、menu
a. 获取目标控件的信息后,取得位置,然后使用adb发送点击位置的指令。用java代码举例:
String bounds = targetElement.attributeValue('bounds');
ArrayList listInt = new ArrayList();
String number = '';
for (int i = 0; i
if (Character.isDigit(bounds.charAt(i))) {
number += bounds.charAt(i);
} else {
if (!number.equalsIgnoreCase('')) {
listInt.add(Integer.valueOf(number));
number = '';
}
}
}
int left = listInt.get(0);
int top = listInt.get(1);
int right = listInt.get(2);
int bottom = listInt.get(3);
String cmd = 'adb shell input tap ' + String.valueOf(right - left) + ' ' + String.valueOf(bottom - top);
Runtime.getRuntime().exec(new String[]{'/bin/bash', '-c', cmd});
b. 往控件里面输入文本,需要输入框首先获取光标,然后再使用adb命令发送输入文本指令。用java代码举例:
String cmd = 'adb shell input text ' + text;
Runtime.getRuntime().exec(new String[]{'/bin/bash', '-c', cmd})
c. 输入返回、Home、Menu实体按键,使用adb命令发送按键指令。用java代码举例:
返回键:
String cmd = 'adb shell input keyevent 4';
Runtime.getRuntime().exec(new String[]{'/bin/bash', '-c', cmd});
Home键:
String cmd = 'adb shell input keyevent 3';
Runtime.getRuntime().exec(new String[]{'/bin/bash', '-c', cmd});
Menu键:
String cmd = 'adb shell input keyevent 1';
Runtime.getRuntime().exec(new String[]{'/bin/bash', '-c', cmd});
5. 实例分析
自动化框架的点击、输入文本、实体按键直接封装成方便方法,比如需要点击某个resource-id为“abc”的控件,可以使用方法“clickByResId('abc')”来实现功能,一行代码就足够,可以使大大减少自动化脚本的编辑成本。
在运行自动化脚本的过程中,会存在要操作的控件还没有出现在安卓手机上,这时候需要有一个循环等待的机制来解决这个问题,在控件没有找到的时候,就一直等待,直到目标控件。这种循环等待机制会大大增加脚本的鲁棒性。
在测试安卓手机的过程中,会出现很多权限请求的弹窗,影响脚本继续往下执行,即使有循环等待机制,也会因为弹窗不处理而无限等待下午。针对这个问题,可以在执行测试脚本的同时,新开一个线程轮训地去检查安卓手机界面是否有弹窗,一旦发现弹窗就点击授权跳过。因为主测试进程没有找到目标控件会一直等待,所以弹窗点击授权之后,就可以继续进行测试。以java代码举例:
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (hasObject('权限请求'){
clickByText('允许');
}
Thread.sleep(1000);
}
}
}).start();
6. 结语
通过自动化框架,可以提高编辑脚本的效率,降低脚本出错的概率,帮助缺少开发经验的软件测试人员更容易地书写测试脚本,推进自动化测试。
参考文献
[1] 郑婷婷,黄英持,Android应用的多设备自动化测试实现[J].软件导刊,2016(02)
联系客服