1. 简介

1.1 概要

AppCrawler 是由霍格沃兹测试学院校长思寒开源的一个项目,通过名字我们大概也能猜出个方向,Crawler 是爬虫的意思,App 的爬虫,遍历 App :

官方 GitHub 上对这款工具的解释是:

一个基于自动遍历的 App 爬虫工具。支持 Android 和 iOS,支持真机和模拟器。最大的特点是灵活性,可通过配置来设定遍历的规则。

这里顺便提一下的是谷歌也发布了一款自动遍历的工具,名字几乎一样,叫做 App Crawler (差了一个空格),设计的思想也一致,但是这款工具目前还在开发完善中,思寒大佬的工具比谷歌的早了两年时间,厉害啊!

下面来看看 AppCrawler 的作用和价值。

1.2 需求背景

互联网的业务需求背景:

业务变更快速
业务线众多
业务流程复杂
依赖第三方接口较多
测试工作常见问题:

UI 自动化只能覆盖核心业务逻辑,新功能来不及上自动化
产品业务测试量较大,新版发布后,老功能来不及全面回归,容易漏测
时间长,强度大的工作后,人容易产生疲乏,对数字的位数,文字的显示等错误信息的敏感度下降
产品的界面深度很深,且包含大量的展示信息功能
专项测试回归难度大:内存泄漏、健壮性测试、弱网等测试太多
这个时候我们需要一种手段,可以达到两方面的目的:

Code less: UI 自动化用例维护成本降到最低
Automate: 尽可能的自动化覆盖回归业务

而自动遍历就可以满足我们对上述的业务的需求;接着再来看我们对自动遍历测试的一些需求,既然要用自动遍历,那么具体要等到什么样的效果?

  1. 工具选择
    2.1 遍历工具需求

自动遍历的需求:

可控:可以定义遍历的路径,指定需要测试的业务,保证核心业务的覆盖优先级
可定制:可实现自动输入、自动滑动等基础行为
结果分析:

点击前后的截图对比
结果的数据建模
2.2 工具对比

2.2.1 Monkey
首先来看业界用的较早也是经常听过的一款工具—— Monkey

这是 Android 官方提供的一个工具,在 Android 的官网我们可以看到对这款工具的解释如下:
没错,谷歌原本设计这款工具是为了对 App 进行压力测试的,而并不是自动遍历测试,注意的是这里的压力测试并不是我们平常意义上的对服务端的压力,而是对 App 前端的压力。下面是思寒对 App 压力测试的原因解释:

谷歌早期在设计 Android 的时候,Android 需要响应滑动、输入、音量、电话等事件,早期 activity 设计不完善的时候,谷歌希望测试 activity 的性能,把所有的数据批量化的输出给 activity,看 activity 一秒钟可以处理多少数据。所以早期 Monkey 是用来做 Android 的一个压力测试的工具。

由于 Monkey 在测试过程中的“随机”性,恰巧可以被用来做自动遍历测试,但是 monkey 的缺点行业很明显,就是不满足我们的两个自动遍历需求:可控性和可定制。

缺点:不支持业务行为定制,无法灵活的控制,经常会点到外部的 App 无法回归原测试 App;或者点击到注销和退出,造成无法继续后面的测试;因此 monkey 在经过调研了解后没有成为我们做自动遍历测试的首选。
2.2.2 Maxim

Maxim 也是一款自动遍历工具,由我们国内的一名叫做 zhangzhao 的工程师开发,官方给出的定义是:

An efficient Android Monkey Tester, available for emulators and real devices 基于遍历规则的高性能 Android Monkey,适用于真机/模拟器的 APP UI 压力测试。

我们来看看这款工具的优缺点:

优点:

基于Monkey二次开发,也用了一些 AppCrawler 的设计思路,拥有定制化功能;
因为底层基于了 Monkey,所以运行速度还是比较快的;
缺点:

因为是基于 Monkey,所以不具备跨平台性,只能测试 Android,不能测试 iOS,Web 等;

这款工具没有开源,但是可以直接使用,在 GitHub 上下载后根据官方说明操作即可,这里不做重点说明,后期有空时候专门研究,独立成篇,或者直接参考作者在 TesterHome 上的帖子;

重点来看一下工具的特点和选择性:

  • 配置文件,官方给出了配置文件的示例,以 json 格式进行编写:
    接触过 AppCrawler 后会发现写法非常相似,只不过 AppCrawler 是以 YAML 文件进行书写。

选择:

这也是一款很优秀的工具,可在一定程度上进行定制,如果只测试 Android 系统的话,可以考虑选用 Maxim 做自动遍历,速度相对较快;如果想要跨平台或者对开源工具进行二次开发,那就要 AppCrawler 登场了。

2.2.3 AppCrawler
再来看今天的主角 AppCrawler,看看它为何满足我们的测试需求,它的优缺点有在哪里。

先来看它与其他框架的关系结构

与其他框架的关系
优点:

跨平台性:AppCrawler 是基于 Appium 开发的,所以支持 Android 和 iOS。
可控性:对测试的页面,控件类型的选择,测试的深度等都可自由控制;
可定制:可自定义操作,如输入,滑动等;

缺点:

运行速度较慢:AppCrawler 是基于 Appium 开发具备了跨平台的优点,但是也因为这层封装造成了运行速度相对较慢;
使用门槛高:正因为使用灵活性的问题,也造成了使用门槛的提高,主要基于 YAML 文件中使用 Appium 的相关技术知识进行配置,这就对使用者有了一定的技术要求;
安装和启动

3.1 下载

这里以目前最新的2.4.0为例
如何自己编译打包:

1)从 GitHub 上 Clone 源码,当前开源的最新 2.4.0 版本对应的分支是 2.3.1
2)切换到分支:git checkout 2.3.1

3)执行 mvn clean compile

4)使用 maven 构建:执行 mvn assembly:single 命令进行编译即可

安装 :

AppCrawler 本身是个 jar 包,不需要安装,需要安装的是运行时所依赖的环境:

Java版本:Java8、Java10 (未测试过,作者说支持)

Appium:Appium 1.8 以上 因为 AppCrawler 是基于 Appium 开发的,

所以 Appium 的环境是必不可少的Appium的安装方式可参考另外一篇博客: Windows (Win10)、Mac 下安装 Appium;

查看帮助文档:

直接使用命令 java -jar appcrawler-2.4.0-jar-with-dependencies.jar,可以看到如下帮助文档信息 相关参数含义和部分注解如下:

$ java -jar appcrawler-2.4.0-jar-with-dependencies.jar


AppCrawler 2.4.0 [霍格沃兹测试学院特别纪念版]
Appium 1.8.1 Java8 tested
app爬虫, 用于自动遍历测试. 支持Android和iOS, 支持真机和模拟器
项目地址: https://github.com/seveniruby/AppCrawler
移动测试技术交流: https://testerhome.com
联络作者: seveniruby@testerhome.com (思寒)
致谢: 晓光 泉龙 杨榕 恒温 mikezhou yaming116 沐木


Usage: appcrawler [options]

-a, --app Android或者iOS的文件地址, 可以是网络地址, 赋值给appium的app选项 #安装App,实际中使用较少
-e, --encoding set encoding, such as UTF-8 GBK #在Windows下可能会产生乱码,对其编码格式进行设置
-c, --conf 配置文件地址 #复杂且重要,是AppCrawler定制的核心
-p, --platform 平台类型android或者ios, 默认会根据app后缀名自动判断
-t, --maxTime 最大运行时间. 单位为秒. 超过此值会退出. 默认最长运行3个小时
-u, --appium appium的url地址 #运行依赖于appium,不加此参数就使用默认的appium地址端口
-o, --output 遍历结果的保存目录. 里面会存放遍历生成的截图, 思维导图和日志
–capability k1=v1,k2=v2… # 和appium的capability设置一致
appium capability选项, 这个参数会覆盖-c指定的配置模板参数, 用于在模板配置之上的参数微调
-r, --report 输出html和xml报告
–template 输出代码模板
–master master的diff.yml文件地址
–candidate candidate环境的diff.yml文件
–diff 执行diff对比
-vv, --verbose 是否展示更多debug信息
–demo 生成demo配置文件学习使用方法
–help
示例
appcrawler -a xueqiu.apk
appcrawler -a xueqiu.apk --capability noReset=true
appcrawler -c conf/xueqiu.json -p android -o result/
appcrawler -c xueqiu.json --capability udid=[你的udid] -a Snowball.app
appcrawler -c xueqiu.json -a Snowball.app -u 4730
appcrawler -c xueqiu.json -a Snowball.app -u http://127.0.0.1:4730/wd/hub

#生成demo例子
appcrawler --demo

#启动已经安装过的app
appcrawler --capability “appPackage=com.xueqiu.android,appActivity=.view.WelcomeActivityAlias”

#从已经结束的结果中重新生成报告
appcrawler --report result/

#新老版本对比
appcrawler --candidate result/ --master pre/ --report ./

这里顺便说一下的是当前版本的diff功能还不完善,也相对较复杂,目前先不做深入研究

Quick Start:

1) 启动appium
2)启动模拟器或真机,保证 adb devices 可有找到你的设备
3) 根据参考文档中的命令,启动遍历一个已经安装过的 App (以示例中的雪球 App 为例):
这个命令执行后会以默认的方式去执行用例,然后遍历

遍历原则:它的遍历原则是,找页面的里层次最深的元素,也就是处于中心位置元素会被优先遍历
部分遍历效果展示:
测试结果

如果没有使用 -o 参数指定 log 输出的路径,AppCrawler 就会在当前目录下生成以时间为命名的文件夹,里面保存了所有的数据,文件、截图、log
打开文件夹会发现如下,每一步都会进行截图(这也是速度变慢的原因之一吧)以及对于的 dom 文件,这里会看到有几个 steps 文件,这个只是随意点了某个操作来告知用户正在操作,真正的执行步骤是从这之后开始。
测试报告在测试 log 中有一个 index.html 文件,打开它会看到刚才运行的测试报告,AppCrawler 会把每一次点击当做一个测试用例,没一个页面当做是一个测试套件;将界面和界面内的控件点击模拟成了测试套件和测试用例的关系;
成功的用 Succeed 表示,Canceled 是遍历的时候发现有这个可点击的控件,但是最后却没遍历到的控件。
报告中也可以查看对应页面操作事件的截图
测试 log在生成的文件夹中有 appcrawler.log,里面记录了详细的执行步骤的 log 信息(加上 -vv 参数运行的话会得到更多更多的 log 信息)
截取部分 log 展示如下:

2019-11-29 15:48:10 INFO [Crawler.996.doElementAction] current element = MainActivity.tag=ImageView.depth=24
2019-11-29 15:48:10 INFO [Crawler.997.doElementAction] current index = 2
2019-11-29 15:48:10 INFO [Crawler.998.doElementAction] current action = click
2019-11-29 15:48:10 INFO [Crawler.999.doElementAction] current xpath = //[@resource-id=“com.xueqiu.android:id/decor_content_parent”]//[@resource-id=“android:id/content”]//[@resource-
id=“com.xueqiu.android:id/mainContent”]//
[@resource-id=“com.xueqiu.android:id/main_content”]//[@resource-
id=“com.xueqiu.android:id/pager”]//
[@resource-id=“com.xueqiu.android:id/layout_refresh”]//[@resource-
id=“com.xueqiu.android:id/list”]//
[@resource-id=“com.xueqiu.android:id/today_topic_container”]//[@resource-
id=“com.xueqiu.android:id/time_line_topic_item_case2”]//
[@resource-
id=“com.xueqiu.android:id/today_topic_container”]//[@resource-
id=“com.xueqiu.android:id/time_line_topic_footer”]//
[@resource-id=“com.xueqiu.android:id/feedback”]
2019-11-29 15:48:10 INFO [Crawler.1000.doElementAction] current url = MainActivity
2019-11-29 15:48:10 INFO [Crawler.1001.doElementAction] current tag path =
hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.view.ViewGroup/androidx.viewpager.widget.ViewPager/android.widget.RelativeLayout/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.ImageView
2019-11-29 15:48:10 INFO [Crawler.1002.doElementAction] current file name = MainActivity.tag=ImageView.depth=24
2019-11-29 15:48:10 INFO [Crawler.1071.doElementAction] need input click
2019-11-29 15:48:10 INFO [AppiumClient.53.findElementByURI] find by uri element= MainActivity.tag=ImageView.depth=24
2019-11-29 15:48:10 INFO [AppiumClient.245.findElementsByURI] findElementByAndroidUIAutomator new UiSelector().className(“android.widget.ImageView”)
2019-11-29 15:48:10 INFO [AppiumClient.60.findElementByURI] find by xpath success
2019-11-29 15:48:10 INFO [Crawler.1080.doElementAction] mark 20191129154742/1_Steps.tag=.name=NOT_FOUND.clicked.png to 20191129154742/2_MainActivity.tag=ImageView.depth=24.click.png
2019-11-29 15:48:10 INFO [AppiumClient.141.mark] read from 20191129154742/1_Steps.tag=.name=NOT_FOUND.clicked.png
2019-11-29 15:48:11 INFO [AppiumClient.154.mark] write png 20191129154742/1_Steps.tag=.name=NOT_FOUND.clicked.png
2019-11-29 15:48:11 INFO [AppiumClient.161.mark] ImageIO.write newImageName 20191129154742/2_MainActivity.tag=ImageView.depth=24.click.png
2019-11-29 15:48:11 INFO [Crawler.1095. a n o n f u n anonfun anonfundoElementAction$5] click element

index 等于几就表示第几次事件,action 表示当前的操作,xpath 就表示当前操作的元素的 xpath 表达式。4. 补充说明

总说 AppCrawler 慢,其他工具相对较快,原因为何,先来看他们的架构组成
底层有个叫 AccessibleServices 东西,它可以获取 Android 所有界面的控件,uiautomator获取元素进行操作的时候就是靠 AccessibleServices 去获取控件,然后去触发一定的行为,uiautomator 就是将其进行了包装;

基于 uiautomator,Appium 开发了一个 uiautomator server,ATX 开发了一个uiautomator2,maxim 就处于这一层。

Appium 走的是 HTTP 协议,ATX 走的是 JSON-RPC 协议,AppCrawler 处于最上层 所以 AppCrawler 由于多了两层封装,再加上运行过程中加入了截图(可以在配置中取消,但是取消后不利于结果的查看),运行起来自然就慢了。

改进期望:后期期望 AppCrawler 团队可以将其根据需求指定底层操作,绕过很多不必要的流程来增加效率,这样功能非常完善的同时也能保证效率
(文章来源于霍格沃兹测试学院)

利器 | AppCrawler 自动遍历测试工具实践(一)相关推荐

  1. 怎么通过name配置button_利器 | AppCrawler 自动遍历测试实践(二):定制化配置

    终于到了"啥也不干躺在家就能给社会做贡献"的时候,但有梦想的测试人从不会让自己的生活变得无聊!与其宅在家里数瓜子壳,还不如利用整块时间提升测试开发技能! 定制化配置 自动遍历测试技 ...

  2. AppCrawler自动遍历测试

    AppCrawler 是由 seveniruby开源的一个自动遍历测试工具,谷歌有一个叫App Crawler 的遍历工具.AppCrawler具有很大的灵活性,可以自由控制测试页面,控件类型,测试深 ...

  3. 初探自动遍历测试工具-AppCrawler

    1.简介 1.1 概要 AppCrawler是由TesterHome联合创始人黄延胜(思寒)大佬开源的一个项目,通过名字我们大概也能猜出个方向,Crawler是爬虫的意思,App的爬虫,遍历App:官 ...

  4. 自动化测试的理想境界:AppCrawler自动遍历工具

    内容来源:2017 年 6 月 24 日,TesterHome联合创始人黄延胜在"Testwo第一届测试分享沙龙"进行<App crawler自动遍历工具>演讲分享.I ...

  5. 自动渗透测试工具集APT2

    自动渗透测试工具集APT2 APT2是Kali Linux新增的一款自动渗透测试工具集.它可以进行NMAP扫描,也可以直接读取Nexpose.Nessus和NMAP的扫描结果,然后自动进行渗透测试.在 ...

  6. android循环遍历assert,AppCrawler自动遍历工具

    前言 AppCrawler是一个基于自动遍历的app爬虫工具. 支持android和iOS, 支持真机和模拟器. 最大的特点是灵活性. 可通过配置来设定遍历的规则. AppCrawler地址 环境准备 ...

  7. android 回归测试,自动遍历回归测试工具

    一.Monkey 随机点击200个事件:adb shell monkey -p com.xxxxx.android  200 每秒10个随机事件:adb shell monkey -p com.xue ...

  8. 03-17 APP自动遍历测试技术

    monkey 是一个在模拟器或者设备上运行的程序,用于生成用户事件的伪随机流 安装 Android SDK 自带 使用 基本配置选项 adb shell monkey 100 # 对所有包随机操作 1 ...

  9. nmon结果分析工具_Jmeter测试工具实践:如何为Jmeter开发测试插件定制专属取样器?...

    JMeter原生支持多种不同的取样器(HTTP.TCP.JDBC.JMS等),每一种不同类型的取样器可以向服务器发送不同协议类型的请求.除了开箱即用的协议支持以外,JMeter还支持用户自己开发新协议 ...

最新文章

  1. 92django_url
  2. boost::posix_time模块实现闹钟的测试程序
  3. HashMap中put方法的过程
  4. 小a与黄金街道(欧拉函数)/**模运算规则总结*/
  5. 关于BI商业智能的“8大问”|一文读懂大数据BI
  6. python画关系网图_使用python绘制人人网好友关系图示例
  7. Go入门之——GOROOT、GOPATH、GOBIN 、Project目录
  8. java图形接口_java基础七 [图形用户接口](阅读Head First Java记录)
  9. Spring Boot入门(2)-项目属性配置
  10. 怎样批量修改照片分辨率?
  11. js根据年份计算总周数并获取每周的日期范围
  12. activiti 流程设计模型(model) 和 部署(deployment)及流程定义(processDefinition)之间的关系;
  13. 平凡的女人,伟大的奉献
  14. opengl对图像进行腐蚀和膨胀
  15. js中substring()、substr() 、slice()的用法
  16. Xen - Networking
  17. MATLAB解决工业机器人建模笔记——atan2函数MATLAB实现
  18. 全球名校AI课程库(2)| 吴恩达 · 机器学习专项课程『Machine Learning』
  19. python爬取猫眼电影
  20. 使用阿里云服务器搭建网站

热门文章

  1. 一键部署工具easy-jenkins,界面友好,操作简单
  2. 03《需求模式——软件建模与分析》
  3. 使用bootstrap模板开发,网页打开很慢的解决办法
  4. 预付费水电表管理系统功能特点
  5. 【MIUI9_7.12.05】小米6 sagit 高通骁龙835 基于安卓N(Android 7.1)时间刺客修改精简优化版本
  6. python实现 基于邻域的算法之协同过滤(电影推荐实战)
  7. CentOS7出现 Detected CPU family 6 model 165 stepping 3
  8. 《火鸡总动员》观后感
  9. SpringCloud开发个人博客项目(框架搭建)
  10. 视频教程-CCNP 思科认证网络工程师(美女讲师版)-思科认证