一 使用目的

该工具主要是基于 appium,可以面向 Android 和 Ios 移动 App,或 H5 或微信等应用的,基于元素识别的 UI 自动化遍历测试.
该工具特点:
1.支持最新的 appium 1.8.1 (AppCrawler 支持 1.7.0)
2.安卓方向支持 monkey 配置遍历.
3.结果报告上看,支持 Crash 信息搜集.会对操作过程录制视频.会对操作过程每动作截图.
其他优质特性详见 github 主页说明

二 资源索引

官方资源

UICrawler Github
UICrawler 配置文件说明
UICrawler 环境配置说明

博客相关

基于 Appium 的 App UI 遍历工具 (支持操作步骤回放)
网盘下载链接

三 环境准备

以安卓方向取重点:

Oracle Java 部署

下载地址 http://www.oracle.com/technetwork/java/javase/downloads/index.html
找到合适的 java 版本下载,我选择的是 jdk-8u91-windows-x64.exe。按步骤安装即可。安装路径一般默认。

配置 java 环境变量:
JAVA_HOME 变量值为 JDK 的安装目录,笔者为 C:\Program Files\Java\jdk1.8.0_91
PATH PATH 变量值后追加 ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
CLASSPATH 变量值为 ;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;

检查是否安装成功

C:\Users\cmd>java -version
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b15, mixed mode)

Android sdk 部署

下载地址 android-sdk_r24.4.1-windows 处下载 android-sdk_r24.4.1-windows.zip
将 android-sdk-windows 解压到你需要的目录下,笔者是 D:\Android\android-sdk-windows

配置 android-sdk 环境变量:
ANDROID_HOME 变量值为 android-sdk 的解压目录,笔者为 D:\Android\android-sdk-windows
PATH PATH 变量值的最后追加 ;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\build-tools;

接下来你便可以用 D:\Android\android-sdk-windows 下的 SDK Manager.exe 下载配置 SDK 或 AVD Manager.exe 配置 AVD 模拟器了。
如果你需要测试 android 应用的话,请先安装配置好某一版本的 SDK 及其相关工具。
如下图,SDK manager 必要配置:
Tools->Options 设置:

其它要下载的:
我目前的配置是

此处的按需选择与 AVD 模拟器配套使用的:

#检查下最终的adb版本
C:\Users\cmd>adb version
Android Debug Bridge version 1.0.39
Version 0.0.1-4500957
Installed as D:\Android\android-sdk-windows\platform-tools\adb.exe

appium 部署

可以用两种方式:
一种就是直接用 desktop 版本, appium-desktop
一种就是 nodejs 部署参考,教您完美 win10 安装 Appium1.7.2 支持 win 客户端自动化
(建议使用 nodejs 部署方式,该文可以完美安装当然你不做 winuiauto 的话可以忽略文中提到的那些 winuiauto 相关的报错)

手机真机相关设置

真机小米 Mix2
需要开启真机开发者选项->USB 调试,模式和其他相关,主要是调试这一栏要打开的有


哦,还有就是接上手机的时候,小米 Mix 会提示选择"USB 用途" (有 1 仅限充电 2 传输文件 MTP 3 传输照片 PTP) 你需要选择 传输文件 MTP 该项.否则 adb devices -l 会报一个类似权限未获取到的提示.

部署 UICrawler 相关

目前尚未完全开源,可以直接去网盘下载 UICrawler-2.0.jar 和 config.yml 到本地磁盘即可.
我是先 git clone https://github.com/lgxqf/UICrawler.git 然后将上述下载的文件放入.

先通过自带的-h 命令检查 UICrawler-2.0 是否正常

D:\UICrawler>java -jar UICrawler-2.0.jar -h
15:32:08.083 [main] INFO  Crawler -     -h  Print this usage information
    -a  Android package's main activity
    -b  iOS bundle id
    -c  Maximum click count
    -f  Yaml config  file
    -m  run monkey
    -p  Android package name
    -t  Appium port
    -u  Device serial
    -w  wda port for ios

四 配置修改

config.yml 用文本编辑器打开,个人推荐 win 环境用 Notepad++,ubuntu 环境用 Notepadqq.
并且打开"显示所有字符",以便查看是否符合 yml 文件编辑格式规范,空格 回车换行符什么的.

配置参考:
YAML 语言格式
XPath 教程

附上最终修改后配置:

GENERAL:
  #截屏数量
  SCREENSHOT_COUNT: 500
  #Crash时截图显示步骤数量
  CRASH_PIC_COUNT: 5
  #遍历深度
  MAX_DEPTH: 2000
  #点击次数
  MAX_CLICK_COUNT: 100000
  #TIME
  DEFAULT_WAIT_SEC: 10
  #查找元素的间隔时间
  DEFAULT_POLLING_INTERVAL_SEC: 5


DEFAULT_VALUE:
  #Appium server IP, 0.0.0.0代表Server在本地
  APPIUM_SERVER_IP: 0.0.0.0
  #Appium端口
  PORT: 4723
  #IOS 才会用到WDA_PORT
  IOS_WDA_PORT: 8001
  #是否忽略Crash,设为true时,crash后会重启app然后继续遍历
  IGNORE_CRASH: true
  ENABLE_VERTICAL_SWIPE: true

#设置MONKEY事件百分比 各事件百分比之和为100
MONKEY:
  #运行时间,以分钟计
  MONKEY_RUNNING_TIME:  6
  #以下各项值总和需为100
  #滑动事件百分比
  SWIPE_RATIO: 10
  #点击事件百分比
  CLICK_RATIO: 80
  #点击MONKEY_SPECIAL_POINT_LIST中的坐标 主要用于触发"返回"功能
  CLICK_SPECIAL_POINT_RATIO: 10
  #重启APP事件百分比
  RESTART_APP_RATIO: 0
  #特殊坐标长按(10秒)
  LONG_PRESS_RATIO: 0
  #Android Only按Home键事件百分比
  HOME_KEY_RATIO: 0

#Gesture https://www.jianshu.com/p/095e81f21e07
  #手势操作
  #双击
  DOUBLE_TAP_RATIO: 0
  #缩小(两指)
  PINCH_RATIO: 0
  #放大(两指)
  UNPINCH_RATIO: 0
  #拖拽
  DRAG_RATIO: 0

#Monkey相关的一些值
MONKEY_LIST:
  #提高测试效率,点击以下点(x,y)时会触发"后退"操作,避免在一个页面停留时间太久
  MONKEY_SPECIAL_POINT_LIST:
  - '60,130'
  - '2100,60'

  #根据以下坐标长按10秒
  LONG_PRESS_LIST:
  - '980,560'

  #设置不点击的区域, radius用来设置以下列坐标为圆心,不想点击的半径区域
  #MONKEY_BLACKLIST_POINT_LIST:
  #- 'radius,10'
  #- '0,0'


#小程序
MINI_PROGRAM:
  #小程序的名字
  MINI_PROGRAM_NAME: 学而思营业厅
  #小程序的进程
  MINI_PROGRAM_PROCESS: com.tencent.mm:appbrand1

#以下的内容很关键,而且需要根据不同的APP定制
CRITICAL_ELEMENT:
  #Android 包名和启动的Activity
  ANDROID_PACKAGE: com.huasheng.stock
  ANDROID_MAIN_ACTIVITY: .Loading

  #IOS Bundle ID com.apple.mobilesafari
  IOS_BUNDLE_ID: com.tencent.xin
  #手机桌面上显示的APP的名字
  IOS_BUNDLE_NAME: 微信
  #IPA名字的前缀
  IOS_IPA_NAME: wechat


#构建XPATH需要的一些内容
  #UI底部TabBar
  ANDROID_BOTTOM_TAB_BAR_ID: com.***.***:id/mainTabLayout
  IOS_BOTTOM_TAB_BAR_TYPE: XCUIElementTypeTabBar

  #注意属性值要加引号''
  ANDROID_CLICK_XPATH_HEADER: "//*[contains(name(), 'Text') and string-length(@text)<10] | //*[contains(name(), 'Image')] | //*[contains(name(), 'Button')]"
  IOS_CLICK_XPATH_HEADER: '@visible="true" and string-length(@value)<30'

  #注意属性值要加双引号""
  ANDROID_USERNAME:
    XPATH: '//*[@resource-id="com.***.***:id/account_num"]'
    ACTION: input
    VALUE: '137******'
  ANDROID_PASSWORD:
    XPATH: '//*[@resource-id="com.***.***:id/pwd"]'
    ACTION: input
    VALUE: 'UICrawler123123'
  ANDROID_LOGIN_BUTTON:
    XPATH: '//*[@resource-id="com.***.***:id/loginbtn"]'
    ACTION: click

  #IOS LOGIN_ELEMENT
  IOS_USERNAME:
    XPATH: '//*[@type="XCUIElementTypeTextField"]'
    ACTION: input
    VALUE: '130xxxxx456'
  IOS_PASSWORD:
    XPATH: '//*[@type="XCUIElementTypeSecureTextField" and @value="请输入登录密码"]'
    ACTION: input
    VALUE: '111111'
  IOS_LOGIN_BUTTON:
    XPATH: '//*[@type="XCUIElementTypeButton" and @name="登录" and @label="登录"]'
    ACTION: click


LIST:
  #待输入文件本的控制类型
  INPUT_CLASS_LIST:
  - android.widget.TextView
  - XCUIElementTypeTextField
  - XCUIElementTypeSecureTextField

  #待输入的文本
  INPUT_TEXT_LIST:
  - '123'
  - 'ABC'

  #当发现App跳转到一下app时 会触发back键
  PRESS_BACK_KEY_PACKAGE_LIST:
  - 高德地图
  - com.autonavi.minimap
  - com.android.settings

  #除了APP本身的包名外 根据以下包名判断是否跳出了APP.android当app跳转到以下app时被认为是合法,会继续遍历操作.
  ANDROID_VALID_PACKAGE_LIST:
  - com.miui.securitycenter
  - com.android.server.telecom
  - com.lbe.security.miui
  - gallery
  - packageinstaller

  #ios 当app跳转到以下app时被认为是合法,会继续遍历操作
  IOS_VALID_BUNDLE_LIST:
  - 照片

  #白名单 遇到包含以下文本的控件,会多次点击(默认所有控件只点一次)
  ITEM_WHITE_LIST:
  - 确定
  - 允许
  - 退出
  - 取消
  - 已解决

  #不点击包含以下文本的控件
  ITEM_BLACKLIST:
  - 客服
  - 电话
  - 不允许
  - 拒绝
  - 拍照
  - 禁止
  - 呼叫
  - 低电量模式
  - 关闭


  #以下类型的元素及子元素不会被点击
  IOS_EXCLUDE_BAR:
  #手机状态栏
  - XCUIElementTypeStatusBar
  #键盘
  - XCUIElementTypeKeyboard

  #iOS不点击以下类型的元素
  IOS_EXCLUDE_TYPE:
  - XCUIElementTypeOther
  - XCUIElementTypeKey
  - XCUIElementTypeWindow
  - XCUIElementTypeApplication

  #android中不点击以下类型的元素
  ANDROID_EXCLUDE_TYPE:
  - android.widget.FrameLayout
#  - android.widget.ImageButton


  NODE_NAME_EXCLUDE_LIST:
  - selected
  - instance
  - checked
  - naf
  - content

  STRUCTURE_NODE_NAME_EXCLUDE_LIST:
  #iOS
  #- value
  - name

  #Android
  - text

修改的地方并不多,大家可以用 diff 比较工具和原版的 config.yml 比较.
重点说一下这段配置:
原配置如下,含义既是遇到文本元素且<30 的都点击

#注意属性值要加引号''
ANDROID_CLICK_XPATH_HEADER: 'string-length(@text)<30'
IOS_CLICK_XPATH_HEADER: '@visible="true" and string-length(@value)<30'

该段不支持如下写,比如我想如下写,可以跑起来,但拼接出来的"clickable elements xpath:"比较怪异且最后脚本端会报错停止,咨询后发现作者并不打算支持如下写法.

#注意属性值要加引号''
ANDROID_CLICK_XPATH_HEADER:
  - "//*[contains(name(), 'Text') and string-length(@text)<10]"
  - "//*[contains(name(), 'Image')]"
  - "//*[contains(name(), 'Button')]"
IOS_CLICK_XPATH_HEADER: '@visible="true" and string-length(@value)<30'

最终查了下 xpath 语法知识,可以用 | 或来连接多个并列属性,这样跑不会报错且正常.这样就可以点击文本长度大于 3 小于 10,和点击所有图片和 Button 元素.

#注意属性值要加引号''
ANDROID_CLICK_XPATH_HEADER: "//*[contains(name(), 'Text') and string-length(@text)>3 and string-length(@text)<10] | //*[contains(name(), 'Image')] | //*[contains(name(), 'Button')]"
IOS_CLICK_XPATH_HEADER: '@visible="true" and string-length(@value)<30'

五 执行

先通过 adb 命令检查小米 Mix2 真机是否连接正常,且确认真机开发者选项相关开启.

C:\Users\cmd>adb devices -l
List of devices attached
yourSerialNo          device product:chiron model:MIX_2 device:chiron

启动 appium server

C:\Users\cmd>appium --session-override

切到 UICrawler-2.0.jar 目录下执行即可.

D:\UICrawler>java -jar UICrawler-2.0.jar -f config.yml -u yourSerialNo

PS:
注意首次运行自动化脚本时候会向手机安装的相关有:
Unlock

Appium Android Input Manager

Appium Settings

io.appium.uiautomator2.Server.test

io.appium.uiautomator2.Server

注意手机端需要手工点击允许安装.

六 执行结果

会按 SerialNo+ 日期时间生成结果目录:

报告如图:

以上配置和 jar 包在 win10 和 ubuntu18.04 均测试正常通过.

其他配置项继续测试中...

七 运行 UICrawler Monkey

截取部分相关说明,熟悉基本原生 monkey 的便可明白,下述配置既是指只运行点击事件的配置.

#设置MONKEY事件百分比 各事件百分比之和为100
MONKEY:
  #运行时间,以分钟计
  MONKEY_RUNNING_TIME:  6
  #以下各项值总和需为100
  #滑动事件百分比
  SWIPE_RATIO: 0
  #点击事件百分比
  CLICK_RATIO: 100
  #点击MONKEY_SPECIAL_POINT_LIST中的坐标 主要用于触发"返回"功能
  CLICK_SPECIAL_POINT_RATIO: 0
  #重启APP事件百分比
  RESTART_APP_RATIO: 0
  #特殊坐标长按(10秒)
  LONG_PRESS_RATIO: 0
  #Android Only按Home键事件百分比
  HOME_KEY_RATIO: 0

#Gesture https://www.jianshu.com/p/095e81f21e07
  #手势操作
  #双击
  DOUBLE_TAP_RATIO: 0
  #缩小(两指)
  PINCH_RATIO: 0
  #放大(两指)
  UNPINCH_RATIO: 0
  #拖拽
  DRAG_RATIO: 0

#Monkey相关的一些值
MONKEY_LIST:
  #提高测试效率,点击以下点(x,y)时会触发"后退"操作,避免在一个页面停留时间太久
  MONKEY_SPECIAL_POINT_LIST:
  - '60,130'
  - '2100,60'

  #根据以下坐标长按10秒
  LONG_PRESS_LIST:
  - '980,560'

  #设置不点击的区域, radius用来设置以下列坐标为圆心,不想点击的半径区域
  #MONKEY_BLACKLIST_POINT_LIST:
  #- 'radius,10'
  #- '0,0'

启动 appium server

C:\Users\cmd>appium --session-override

传参-m 即可运行配置中的 monkey 相关设置

java -jar UICrawler-2.0.jar -f config.yml -u yourSerialNo -m

执行报告:
我们也可以看到执行的各类 monkey 事件计数

Tips

作者调起的是非原生 monkey,所以当你发现无法正常关掉 UICrawler Monkey,一直在手机中继续跑点击的时候,使用

# Linux下
adb shell ps |grep monkey
# windows cmd下
adb shell ps | findstr monkey 
# 或
adb sehll ps | find "monkey"    找到返回的进程号
#然后 kill掉该手机内原生monkey进程
adb shell kill [刚才查到的进程号] 

# 如windows下 原生monkey类似com.android.commands.monkey:
adb shell ps| findstr monkey
USER      PID   PPID  VSIZE  RSS   WCHAN              PC  NAME
shell     13846 1032  2073652 51480 futex_wait 7f900d7ef0 S com.android.commands.monkey

是找不到该进程,也甭想 kill 掉的, 我们可以 ps -ef|grep UICrawler 相关结束掉本机脚本端的那个 java 进程也就是 . "java -jar UICrawler-2.0.jar -f config.yml -u yourSerialNo -m" 该进程

monkey 配置部分说明1

关于坐标查看,可以打开开发者选项,"输入"该节下的 "指针位置".这样就可以看到坐标系了.

MONKEY_LIST:
  #提高测试效率,点击以下点(x,y)时会触发"后退"操作,避免在一个页面停留时间太久
  MONKEY_SPECIAL_POINT_LIST:
  - '80,160'

  #设置不点击的区域, radius用来设置以下列坐标为圆心,不想点击的半径区域
  MONKEY_BLACKLIST_POINT_LIST:
  - 'radius,10'
  - '0,0'

第一个坐标'80,160',是左上的一般安卓 app 里的"返回"区域,

第二个坐标 - 'radius,10' - '0,0' ,这里 0,0 的话 应该不就是 app 界面左上区域起始点, 然后 x y 偏移 10 画个圆 ,不又是一般安卓 app 里的 "返回"区域?
这样 这两个 第 1 个 和 第 3 个不就冲突了?

这时如果,第 1 和 2 冲突时,以 2 为准 . 即以上效果为不点击左上那个区域, 也就是一般的 app 返回区域.

monkey 配置部分说明2

#设置MONKEY事件百分比 各事件百分比之和为100
MONKEY:
  #运行时间,以分钟计
  MONKEY_RUNNING_TIME:  6
  #以下各项值总和需为100
  #滑动事件百分比
  SWIPE_RATIO: 10
  #点击事件百分比
  CLICK_RATIO: 80
  #点击MONKEY_SPECIAL_POINT_LIST中的坐标 主要用于触发"返回"功能
  CLICK_SPECIAL_POINT_RATIO: 10
  #重启APP事件百分比
  RESTART_APP_RATIO: 0
  #特殊坐标长按(10秒)
  LONG_PRESS_RATIO: 0
  #Android Only按Home键事件百分比
  HOME_KEY_RATIO: 0

#Gesture https://www.jianshu.com/p/095e81f21e07
  #手势操作
  #双击
  DOUBLE_TAP_RATIO: 0
  #缩小(两指)
  PINCH_RATIO: 0
  #放大(两指)
  UNPINCH_RATIO: 0
  #拖拽
  DRAG_RATIO: 0

#Monkey相关的一些值
MONKEY_LIST:
  #提高测试效率,点击以下点(x,y)时会触发"后退"操作,避免在一个页面停留时间太久
  MONKEY_SPECIAL_POINT_LIST:
  - '60,130'
  - '2100,60'

  #根据以下坐标长按10秒
  LONG_PRESS_LIST:
  - '980,560'

  #设置不点击的区域, radius用来设置以下列坐标为圆心,不想点击的半径区域
  #MONKEY_BLACKLIST_POINT_LIST:
  #- 'radius,10'
  #- '0,0'

该节为所有 UICrawler Monkey 配置
1 MONKEY: 该节 要注意所有事件比率百分比之和要为 100,
2 MONKEY_LIST: 中的 "MONKEY_SPECIAL_POINT_LIST: "对应 MONKEY:节的"# 点击 MONKEY_SPECIAL_POINT_LIST 中的坐标 主要用于触发"返回"功能
CLICK_SPECIAL_POINT_RATIO: 10"
3 MONKEY_LIST: 中的 "LONG_PRESS_LIST:" 对应 对应 MONKEY:节的" # 对应 LONG_PRESS_LIST:特殊坐标长按 (10 秒)
LONG_PRESS_RATIO: 0"
那么上述配置的意思就是,执行点击事件 80%,执行滑动事件 10%,点击特殊区域坐标事件 10%

八 结语

之前一直用 AppCrawler 也很优秀,但无奈作者老大搞学院培训,无心维护和深入继续开发,支持也一直停留在 appium1.7.0.
这也就算了,答应过的放出来打算做的特性都还没兑现....
比较使用这两个工具,执行稳定性上 UICrawler 可以连续跑很久 (我最长跑了 1 小时回来还在继续跑且当前脚本配置来看截图执行的点击比较细腻且有规律),且脚本执行端不会报错,但 AppCrawler 10 次 会有个 3 次左右,脚本执行端会报错且无法继续执行下去,另有些配置效果 AppCrawler 我并未完全吃透和试验出来.

补充说明

2018年6月29日追加
目前时间截点的 config 版本,该配置参数 MONKEY_RUNNING_TIME: 6 已被 CRAWLER_RUNNING_TIME 合并。请已官方 github 发布为准。

cmd@TR:~/UICrawler$ java -jar UICrawler-2.0.jar -h

16:41:03.088 [main] INFO  Crawler -     -h  Print this usage information

    -a  Android package's main activity

    -b  iOS bundle id

    -c  Maximum click count

    -d  Maximum crawler UI depth

    -f  Yaml config  file

    -i  ignore crash

    -l  loop count

    -m  run monkey

    -p  Android package name

    -r  Crawler running time

    -t  Appium port

    -u  Device serial

    -v  Version

    -w  WDA port for ios

-p 指定 package 就会保证不退出 app 或者退出 APP 了 能自己再重起.
-l loop count 循环次数,即一个 Crawler running time 遍历时间结束后,继续再跑几个 Crawler running time。比如遍历时间 6 分钟,6 分钟结束后 ,如果-l 是 3 那就继续再跑 2 遍 6 分钟遍历,共 3 次。

#当发现App跳转到以下app时 会触发back键

  PRESS_BACK_KEY_PACKAGE_LIST:

  - 高德地图

  - com.autonavi.minimap

  - com.android.settings

getpacgesource 里返回的值 只要 contains 关键字 就 trigger back key 。即遇到当前被遍历的界面上包含配置的关键字即会触发 back 键。

疑惑与答疑
那这段配置遇到以下 app 就 back 是为了什么效果?跳到高德以后 会返回到 app,不然会一直在高德里遍历。

..................... 那不和 -p 一样的效果 (-p 发现遍历的不是指定 app 了 也要重起 app)

不一样啊,重启 launch app 和触发返回 操作不一样 你想想是不是。

那就是面向两种场景的处理,保证不跳出遍历 app。

补充记录:

2018年10月24日
已升级为 appium1.9.1 ,在 ubuntu18.04.1 windows10 升级后,均重跑 UICrawler2.21 config 配置不变成功
升级记录
https://testerhome.com/topics/12988#reply10
(以上为 win10 版本且带支持做 win32 uwp win 应用 UI 自动化的 appium1.9.1 升级方式.)


↙↙↙阅读原文可查看相关链接,并与作者交流