移动测试开发 UI 遍历的初步尝试
对于测试人员, UI 遍历已经很普遍了,比如说 Monkey, UICrawler 等等,都可以进行 UI 遍历。那我们怎么按照顺序去遍历一个 app 呢。下面介绍一个 360 开测平台上使用的用 uiautomator 做的 UI 遍历。
实现步骤
需要的参数: 包名, 启动类名,遍历截止类名,遍历时间,遍历总步数,遍历中需要登录的账号,登录密码。
实现思路:
- 启动当前的 apk
- 添加界面变化监听
- dump 界面组件元素
- 排列界面组件元素
- 比对界面元素
- 操作界面组件元素,截图绘制
- 遍历结束,停止 UI 遍历
详细说明
步骤 1
启动当前的 apk
初始化参数配置
步骤 2
监听界面变化,这里我们添加 AccessibilityService 进行界面变化的监听,主要监听界面的三个变化,TYPE_WINDOW_STATE_CHANGED, TYPE_WINDOW_CONTENT_CHANGED,TYPE_VIEW_CLICKED 窗口变化,窗口内容变化, 点击事件变化监听。
我们做一些初始化的判断:
1.包名是否正确
// 判断是否监听到了包名
if (null != event.getPackageName()) {
if (TextUtils.isEmpty(event.getPackageName().toString())) {
LoggerEx.getLogger().error("包名获取为空, 返回...");
return;
}
if(ClassNameUtils.dumpISDesk(event.getPackageName().toString())) {
LoggerEx.getLogger().error("任务停止..包名不对应..." + event.getPackageName().toString());
endTraverse();
return;
}
} else {
return;
}
2.类名是否获取成功
// 获取当前显示界面的类名
String classname = getClassName();
if (TextUtils.isEmpty(classname)) return;
3.软件盘弹出来了,关掉软件盘输入
// 首先把软键盘给关闭掉
if(ViewTraverseTools.getInstance().closeKeyWord()){
LoggerEx.getLogger().error("软件盘出现...");
closeKeyBoard(); // 当前软键盘是打开状态,我们要把软件盘给关闭掉
}
步骤 3,4
dump 界面组件元素,我们在这里只 dump 一些我们可以操作的界面元素,比如说可以点击的,可以滑动的界面元素。
在 dump 的过程中,我们可以按照一般的 app 出现的特殊情况进行一个排序,比如列表的话,我们只取在界面范围内的元素,ViewPage ,我们可以优先取出来:
判断 列表在点钱界面有几个子界面可以 dump:
/**
* listview item count is show screen
*
* 我们判断一下当前界面的listview 有几个子项可点
*/
private int listViewShow(AccessibilityNodeInfo node, int count){
int numberChildForList = 0;
for(int i = 0; i < count ; i++){
if(isInScreen(node.getChild(i))){
numberChildForList++;
}
}
return numberChildForList;
}
判断当前的控件是否显示在可见屏幕范围内:
保存数据:
步骤 5
比对界面元素,判断当前要操作的组件。
我们怎么比对当前界面操作的元素呢:这里分为两种比对方式
MD5 比对, 在存储的串中,当前操作的 MD5 是否和当前界面生成的 MD5 是否相同。
比对图片的相似度,每点击一次,比对一个图片相似度,如果存在相同的部分,直接抽取数据进行排列组合生成一个新的 list
步骤 6
操作界面元素
步骤 7
停止 UI 遍历
停止条件: 遍历时间和设置时间相同, 遍历步数和设置的步数相同, 返回手机屏幕界面,遍历结束
// 当主页面的步数小于等于0 ,或者 时间结束,或者
if (mainPage <= 0 || (System.currentTimeMillis() - startTime > allTime)) {
LoggerEx.getLogger().error("任务停止..操作超出上线...");
endTraverse();
return;
}
效果