移动测试开发 UI 遍历的初步尝试

opentest-oper@360.cn · July 10, 2019 · Last by opentest-oper@360.cn replied at December 24, 2019 · 3310 hits

对于测试人员, UI 遍历已经很普遍了,比如说 Monkey, UICrawler 等等,都可以进行 UI 遍历。那我们怎么按照顺序去遍历一个 app 呢。下面介绍一个360 开测平台上使用的用 uiautomator 做的 UI 遍历。

实现步骤

需要的参数: 包名, 启动类名,遍历截止类名,遍历时间,遍历总步数,遍历中需要登录的账号,登录密码。

实现思路:

  1. 启动当前的 apk
  2. 添加界面变化监听
  3. dump 界面组件元素
  4. 排列界面组件元素
  5. 比对界面元素
  6. 操作界面组件元素,截图绘制
  7. 遍历结束,停止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

比对界面元素,判断当前要操作的组件。

我们怎么比对当前界面操作的元素呢:这里分为两种比对方式

  1. MD5 比对, 在存储的串中,当前操作的MD5是否和当前界面生成的MD5是否相同。

  2. 比对图片的相似度,每点击一次,比对一个图片相似度,如果存在相同的部分,直接抽取数据进行排列组合生成一个新的 list

步骤6

操作界面元素

步骤7

停止UI遍历

停止条件: 遍历时间和设置时间相同, 遍历步数和设置的步数相同, 返回手机屏幕界面,遍历结束

// 当主页面的步数小于等于0 ,或者 时间结束,或者
if (mainPage <= 0 || (System.currentTimeMillis() - startTime > allTime)) {
LoggerEx.getLogger().error("任务停止..操作超出上线...");
endTraverse();
return;
}

效果


如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 7 条回复 时间 点赞

h5的问题怎么解决呢

MarvinWu 回复

H5页面可以增加AccessibilityServiceInfo.flags的AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY支持,然后就可以获取h5页面的node信息。

请问你这个支持小程序码

Qjping 回复

不支持哟

有demo可供学习么,😟 想实现基于AccessibilityService的UI遍历点击。

有ios相关的的demo吗?

hongxin0927 回复

IOS暂时未开发

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up