您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
Android端APP稳定性测试实践
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
Android端APP稳定性测试实践
自猿其说Tech
2022-10-19
IP归属:未知
25600浏览
测试
### 1 前言 本文为大家分享快递快运技术部小哥工作台APP端的稳定性测试方法;目前小哥工作台APP只有Android版本,本文也只围绕Android稳定性测试方法进行阐述。 小哥工作台APP是一线快递员小哥日常工作中使用最频繁的工具,绝大部分揽收、派送、站内相关的操作都需要在小哥工作台APP中完成;小哥工作台APP的稳定性直接影响全国10万+快递员小哥的工作效率和使用体验,进而影响整个物流时效及用户服务体验;所以,稳定性是质量体系中最基本也是最关键的一环。 ### 2 什么是APP稳定性测试 APP的稳定性也可以理解为APP的健壮性、可靠性。对被测应用进行长时间的操作,在各种场景使用过程中都可以正常使用,不出现或极少出现崩溃/闪退、无响应等问题。比如一个健康的成年人,出现了普通发烧感冒也不会影响其正常的生活,那么我们会认为其身体还是健康的。 回到APP测试也是一样,如果对被测应用长时间连续进行各种操作,也不会影响APP的正常使用,我们就会认为这款APP在稳定性方面是符合预期的。 ### 3 APP稳定性测试的目的 测试APP是否达到一个相对稳定的状态,验证在长时间频繁持续操作被测APP过程中是否存在Crash/ANR现象产生。 ### 4 如何进行APP稳定性测试 为了更简单的测试小哥工作台APP的稳定性,我们基于Python语言,开发了一套自动化脚本;连接上被测设备后,根据测试诉求配置好需要的参数后,就可以自动收集被测APP的性能指标,并可以生成便于我们阅读和定位问题的测试报告及日志。 #### 4.1 依赖工具 首先介绍2个Android平台下的工具,我们的稳定性测试就是基于他们来实现的: ##### 4.1.1 ADB(Android Debug Bridge) Android 调试桥 (adb) 是Android SDK中的一个工具,是一种功能多样的命令行工具,可让您与设备进行通信,它是一个客户端-服务器端程序。客户端:用于发送命令。客户端在开发机器上运行。您可以通过发出adb 命令从命令行终端调用客户端。守护程序 (adbd):用于在设备上运行命令。守护程序在每个设备上作为后台进程运行。服务器:用于管理客户端与守护程序之间的通信。服务器在开发机器上作为后台进程运行。 它的主要功能有: - 运行设备的shell(命令行) - 管理模拟器或设备的端口映射 - 计算机和设备之间上传/下载文件 - 将本地apk软件安装至模拟器或android设备 ##### 4.1.2 Monkey Monkey是向系统发送随机的用户事件流(如按键输入、触摸屏输入和手势输入等),实现对正在开发的应用程序进行稳定性测试。可以更好的模拟用户操作,确保App的稳定性。 通过Monkey程序模拟用户触摸屏幕、滑动Trackball、 按键等操作来对设备上的程序进行压力测试,检测程序多久的时间会发生异常。 Monkey 程序是由 Android 系统自带,使用 Java 语言写成,其本身是安卓系统下的一个monkey.jar文件。在Android文件系统中的存放路径是: /system/framework/monkey.jar; Monkey.jar程序是由一个名为“monkey”的Shell脚本来启动执行,shell脚本在Android文件系统中 的存放路径是:/system/bin/monkey; Monkey 启动方式:在 cmd 命令提示符里面输入adb命令行来启动 monkey 测试。 命令行:adb shell monkey --> monkey.shell --> monkey.jar --> 安卓进程 --> 设备上执行测试 <center>![](//img1.jcloudcs.com/developer.jdcloud.com/f0518c78-9cf4-4421-940f-9bf0e305bf9e20221019161350.png) 图1 - Monkey执行示意图</center> Monkey命令示例 adb -s emulator-5554 shell monkey -p com.landicorp.jd.delivery --throttle 100 --pct-touch 100 --ignore-timeouts --ignore-crashes --monitor-native-crashes -v -v -v 80000 > 8f99f1f1-d28c-4101-866e-d3aa2902eaa5_monkey.log 参数说明: ![](//img1.jcloudcs.com/developer.jdcloud.com/ad46ec2e-f3d0-4313-beb1-a309f14493bd20221019161420.png) #### 4.2 脚本执行流程 脚本整体的思路是在Monkey测试的过程中,记录被测APP的资源占用情况和设备电池电量情况,以及监控测试过程中可能发生的Crash和ANR现象。 Monkey测试可以模拟随机的“施压”请求,以远超日常操作的频率和非常规的操作路径考验被测APP的健壮性。 <center>![](//img1.jcloudcs.com/developer.jdcloud.com/5c1c8716-9f2e-4541-8aa0-6e2ba67ee6a520221019161435.png) 图2 - APP稳定性测试脚本执行流程</center> 如上图所示,整个过程脚本会自动收集Monkey测试过程中的性能指标数据,并生成便于我们阅读的报告,大致流程如下: 前置条件:根据实际业务预先在被测APP中准备好适量的测试数据,比如,小哥工作台APP揽收和派送订单至少需要500单 1)创建持久化info目录,存放执行过程中记录序列化后的性能指标数据; 2)读取monkey.ini配置文件数据,获取: 被测应用包名,monkey命令参数,监控网络类型,记录日志间隔(单位秒),执行结束标志位; 配置文件示例: [DEFAULT] package_name=com.landicorp.jd.delivery cmd=monkey -p com.landicorp.jd.delivery --throttle 100 --pct-touch 100 --ignore-timeouts --ignore-crashes --monitor-native-crashes -v -v -v 80000 net=wifi gap=1 finished_flag=Monkey finished 字段说明: ![](//img1.jcloudcs.com/developer.jdcloud.com/e3ac6b1c-0ed2-453c-92b7-662cec0dbac320221019161532.png) 3)根据连接设备数量(脚本支持同时在多个连接设备上执行),启用进程池,使用多进程在多个设备上执行,进程阻塞直到结果返回; 4)获取每个连接设备的基本信息,如: - 手机型号 - 设备CPU核数 - 内存信息 - 操作系统版本信息 - 剩余电量 5)根据连接设备名称,为每个设备创建独立的性能数据文件; 6)根据monkey.ini中的配置执行Monkey测试, 执行过程中记录日志信息: - 获取当前设备下被测APP的进程id(pid),根据被测pid,记录手机日志: logcat.log - 创建Monkey测试结果日志:monkey.log - 导出设备端ANR目录下traces.log 7)在Monkey测试过程中,监控各个连接设备的性能指标: - 被测APP的CPU使用率 - 被测APP内存占用率 - 被测APP每秒的帧数 - 被测APP上传/下载流量 - 设备电池电量 8)Monkey日志文件中或手动停止执行Stopper文件中,获取到Monkey执行结束标志后,记录执行前后的电量及执行时间,终止Monkey执行; 9)如果执行结束标位符合要求,将收集到的性能指标数据经过处理后写入到xlsx报告文件中;同时,测试过程中,如果有Crash或者ANR,则将对应的日志记录到xlsx报告文件中; 10)清理掉临时结果数据info目录。 #### 4.3 性能指标监控 其中获取连接设备的硬件信息,及测试过程中性能指标数据都是基于adb命令来实现的;需要额外实现从命令行返回的结果中过滤我们需要的数据,并记录到数据文件中; 具体命令列举如下: ![](//img1.jcloudcs.com/developer.jdcloud.com/c413ded2-32d7-4b1f-8088-0d073e71254620221019161715.png) 变量说明: - ANDROID_SERIAL:连接设备名称;可使用adb devices命令查看; - PACKAGE_NAME:被测APP包名,如:小哥工作台APP包名为 com.landicorp.jd.delivery - PID:被测APP进程ID,可使用命令adb shell "ps | grep com.landicorp.jd.delivery"查找 #### 4.4 日志收集 测试过程中,脚本会收集logcat日志及手机端的traces日志,对于定位Crash/ANR问题提供线索。 <center>![](//img1.jcloudcs.com/developer.jdcloud.com/c9617a83-c135-4aa0-b5b8-310740c4207f20221019161743.png) 图3 - 早期版本小哥工作台APP发生Crash的logcat日志 ![](//img1.jcloudcs.com/developer.jdcloud.com/ae04f2d5-a517-47f6-9d3d-9f812c91995720221019161755.png) 图4 - 早期版本小哥工作台APP发生ANR的traces日志</center> #### 4.5 测试报告 Monkey测试正常结束后,脚本会将测试过程中记录的性能指标数据生成xlxs图表,更加便于阅读。 <center>![](//img1.jcloudcs.com/developer.jdcloud.com/3c4c5862-b7f8-4bf9-afa3-a3157a73dade20221019161836.png) 图5 - 测试结束生成xlsx测试报告</center> 准对一个测试版本,建议连接多个不同的设备同时执行,观察不同设备的稳定性情况;如果只有一个测试设备,建议执行多次,观察该设备每次测试结果的稳定性情况。 同时,在当前版本测试报告中建议附上上个版本的性能监控指标,提供对比数据作为参考,例如: <center>![](//img1.jcloudcs.com/developer.jdcloud.com/2a7fffdb-e340-4d42-b1f3-9da59400b32d20221019161938.png) 图6 - 测试报告中包括上一版本测试结果数据</center> #### 4.6 测试过程中遇到的问题 Q1: Monkey Test本身是无序随机的测试,测试过程中可能会无意点击到顶部工具栏中的飞行模式按钮,WIFI开关按钮等导致Android设备断网离线,或者点击到手电筒开关导致电量消耗增加; 为了规避此类现象,脚本在执行之前会设置连接的Android设备为沉浸模式,即:隐藏顶部工具栏,防止干扰。 Q2:一旦触发Monkey Test执行,只能kill对应的进程来终止执行;在执行过程中,被测应用可能由于发送Crash或者ANR导致后续测试执行无效;如果此时终止脚本的执行,之前的测试结果数据无法保存; 我们提供了手动停止执行的方式来保存当前的结果数据,具体方法: 在log目录中生成的{uuid}_stopper.log中,输入monkey.ini配置文件中配置的finished_flag标志位,如示例中的Monkey finished, 并保存文件; 程序执行过程中脚本读取到stopper.log中有效的停止标志位后就会终止测试,并记录现有的结果数据 Q3:测试报告中上下行流量初始值为什么不是从0开始呢? 在执行稳定性测试之前,设备切换一下飞行模式再关闭飞行模式,这样设备当前的流量消耗记录会被重置为0。 ### 5 APP稳定性判断 #### 5.1 测试结果初步判断 我们常用的方法是分析logcat日志 如果是ANR问题(具体的表现是,系统出现类似这样的提示:APP提示无法响应,是结束进行还是继续等待), 则搜索"ANR" 或 "anr in"关键词快速定位到关键事件信息 ,如: 12-02 21:31:22.350 E/ActivityManager( 389): ANR in com.android.settings (com.android.settings/.SubSettings) 12-02 21:31:22.350 E/ActivityManager( 389): PID: 676 如果是系统crash(具体的表现是,系统出现类似这样的提示:很抱歉,“xxx”已停止运行),会有类似关键字:java.lang.NullPointerException 在这里顺便提一下常见的Java异常: - 算术异常类:ArithmeticExecption - 空指针异常类:NullPointerException - 类型强制转换异常:ClassCastException - 数组负下标异常:NegativeArrayException - 数组下标越界异常:ArrayIndexOutOfBoundsException - 违背安全原则异常:SecturityException - 文件已结束异常:EOFException - 文件未找到异常:FileNotFoundException - 字符串转换为数字异常:NumberFormatException - 操作数据库异常:SQLException - 违法访问错误:IllegalAccessError - 堆栈溢出错误:StackOverflowError - 内存不足错误:OutOfMemoryError - 违法访问错误:IllegalAccessError #### 5.2 判断是否存在内存泄漏 当垃圾回收机在进行垃圾回收之后,会在logcat日志中做相对应的输出,所以我们也可以通过这些信息来判断是否存在内存泄露问题 - GC_FOR_MALLOC: 表示是在堆上分配对象时内存不足触发的GC - GC_EXPLICIT: 表示是应用程序调用System.gc、VMRuntime.gc接口或者收到SIGUSR1信号时触发的GC - GC_CONCURRENT: 当我们应用程序的堆内存达到一定量,或者可以理解为快要满的时候,系统会自动触发GC操作来释放内存 - GC_BEFORE_OOM:表示是在准备抛OOM异常之前进行的最后努力而触发的GC 此外,APP稳定性判断的常用的指标是崩溃率、ANR率。 如果用计算公式来说明那就是:1-崩溃率/ANR率来衡量,崩溃率/ANR率越小,稳定性越好。 测试阶段可以用公式:崩溃率/ANR率 = 崩溃次数(ANR次数) / 总操作次数 * 100% 上线后使用的公式:崩溃率/ANR率 = 一段时间内崩溃用户数 / 一段时间内总用户数 * 100% 我们可以根据项目具体的情况来制定测试通过的阈值,只有测试通过之后才能对外发布版本。 ### 6 影响APP稳定性的因素 常见影响APP稳定性的原因有以下几种: **内存问题** - APP所需内存超过设备限制(如可用内存过低时),导致APP崩溃闪退 - APP内存泄漏,耗尽设备全部内存导致整个系统崩溃 - APP内存越界,使用了非授权的内存位置导致APP崩溃 **程序逻辑错误** - 数组越界,如负数索引、超过数组长度的索引 - 堆栈溢出,如堆栈区缓冲区被填满,堆栈空时取数据等 - 并发操作,如并发时调用了一个已释放的指针 - 逻辑错误,如0作为除数问题 **交互逻辑** - APP界面交换操作滑动导致APP崩溃 - 未处理等中断及异常 - APP在使用过程中面临很多中断、如切后台、接听电话、切换网络、断网以及用户的一些非预期操作 **网络因素** - 比如网络不佳、弱网环境,无法达到APP所需的快速响应时间,导致APP崩溃 - 不同网络的切换 ### 7 结语 Monkey虽然可以根据一个指定的命令发送按键消息,但不支持条件判断,不支持获取被测界面的信息来执行验证操作;因此只是使用Monkey是无法做到特定场景、特定界面的相关测试。后续我们也会针对这个问题做进一步的探索。 ------------ ###### 自猿其说Tech-JDL京东物流技术与数据智能部 ###### 作者:刘飞
原创文章,需联系作者,授权转载
上一篇:基于Seata探寻分布式事务的实现方案
下一篇:自动化测试实践之脚本模块化
相关文章
安全测试之探索windows游戏扫雷
Jmeter压测实战:Jmeter二次开发之JSF采样器实现
Laputa自动化测试框架介绍
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号