Android自动化测试(一)
测试是应用开发中不可或缺的一部分。测试所做的工作,虽然不能让用户看到效果,但是想要保证一个有一定用户基础的应用的稳定性,测试是必须做的,否则严重的崩溃率肯定会导致用户的差评或者流失。
ADB工具
ADB的使用Android开发者应该都很熟悉了,它是电脑和手机之间连接的一个桥梁。电脑端有一个Client和一个Server,Client负责输入命令,Server负责和手机连接,手机端通过adbd跟Server交互.
常用的ADB命令
adb devices
列出电脑连接的设备 和 设备id,设备状态adb push
电脑端推送文件到手机 比如adb -s 设备名 push 1.jpg /data/temp/1.jpg
如果连接了一个设备可以不用自定设备名称adb pull
从手机拉取文件到电脑当前目录(执行命令的路径) 比如adb -s 设备名 pull /data/temp/aaa.jpg .
adb forward
端口转发 比如 adb forward tcp:8888 tcp:9999的意思是,将PC端的8888端口收到的数据,转发给到手机中9999端口adb start-server/adb kill-server
启动/杀死 ADB 服务adb install/adb uninstall
安装/卸载 apk uninstall命令需要指定应用的包名adb shell
可以在电脑上直接进入手机终端界面操作手机- 进入
adb shell
之后 使用pm list packages
可以列出手机上是所有包名
执行 adb 命令需要把 sdk/tools路径配置到环境变量中或者直接进入 sdk/tools 目录中执行这些命令
Monkey
Monkey 是一个命令行工具,可以在任何模拟器实例或设备上运行。它会将伪随机用户事件流发送到系统中,从而对您正在开发的应用软件进行压力测试。
Monkey 包含许多选项,主要分为以下四个类别:
- 基本配置选项,例如设置要尝试的事件数。
- 操作限制条件,例如将测试对象限制为单个软件包。
- 事件类型和频率。
- 调试选项。
Monkey 在运行时会生成事件并将其发送到系统。它还会监视被测系统并查找三种特殊情况:
- 如果您已将 Monkey 限制为在一个或多个特定软件包中运行,它会监视并阻止转到任何其他软件包的尝试。
- 如果应用崩溃或收到任何未处理的异常,Monkey 会停止并报告错误。
- 如果应用生成“应用无响应”错误,Monkey 会停止并报告错误。
根据您选择的详细程度级别,您还将看到有关 Monkey 进度和所生成事件的报告。
Monkey 的基本用法
您可以使用开发计算机上的命令行启动 Monkey,也可以通过脚本启动。由于 Monkey 在模拟器/设备环境中运行,因此您必须从该环境中通过 shell 启动它。为此,您可以在每个命令前面加上 adb shell
,或者直接进入 shell 并输入 Monkey 命令。
基本语法如下:
$ adb shell monkey [options] <event-count>
如果未指定任何选项,Monkey 将以静默(非详细)模式启动,并将事件发送到目标上安装的任何(及所有)软件包。下面是一个更典型的命令行,它会启动您的应用并向其发送 500 个伪随机事件:
$ adb shell monkey -p your.package.name -v 500
命令选项参考信息
下表列出了可以在 Monkey 命令行中添加的所有选项。
类别 | 选项 | 说明 |
---|---|---|
常规 | --help | 输出简单的使用指南。 |
常规 | -v | 命令行上的每个 -v 都会增加详细程度级别。级别 0(默认值)只提供启动通知、测试完成和最终结果。级别 1 提供有关测试在运行时的更多详细信息,例如发送到您的 Activity 的各个事件。级别 2 提供更详细的设置信息,例如已选择或未选择用于测试的 Activity。 |
事件 | -s <seed> | 伪随机数生成器的种子值。如果您使用相同的种子值重新运行 Monkey,它将会生成相同的事件序列。 |
事件 | --throttle <milliseconds> | 在事件之间插入固定的延迟时间。您可以使用此选项减慢 Monkey 速度。如果未指定,则不延迟,系统会尽快地生成事件。 |
事件 | --pct-touch <percent> | 调整轻触事件所占百分比。(轻触事件是指屏幕上的单个位置上的按下/释放事件。) |
事件 | --pct-motion <percent> | 调整动作事件所占百分比。(动作事件包括屏幕上某个位置的按下事件,一系列伪随机动作和一个释放事件。) |
事件 | --pct-trackball <percent> | 调整轨迹球事件所占百分比。(轨迹球事件包括一个或多个随机动作,有时后跟点击。) |
事件 | --pct-nav <percent> | 调整“基本”导航事件所占百分比。(导航事件包括向上/向下/向左/向右,作为方向输入设备的输入。) |
事件 | --pct-majornav <percent> | 调整“主要”导航事件所占百分比。(这些导航事件通常会导致界面中的操作,例如 5 方向键的中间按钮、返回键或菜单键。) |
事件 | --pct-syskeys <percent> | 调整“系统”按键事件所占百分比。(这些按键通常预留供系统使用,例如“主屏幕”、“返回”、“发起通话”、“结束通话”或“音量控件”。) |
事件 | --pct-appswitch <percent> | 调整 Activity 启动次数所占百分比。Monkey 会以随机间隔发起 startActivity() 调用,以最大限度地覆盖软件包中的所有 Activity。 |
事件 | --pct-anyevent <percent> | 调整其他类型事件所占百分比。这包括所有其他类型的事件,例如按键、设备上的其他不太常用的按钮等等。 |
约束条件 | -p <allowed-package-name> | 如果您通过这种方式指定一个或多个软件包,Monkey 将仅允许系统访问这些软件包内的 Activity。如果应用需要访问其他软件包中的 Activity(例如选择联系人),您还需要指定这些软件包。如果未指定任何软件包,Monkey 将允许系统启动所有软件包中的 Activity。要指定多个软件包,请多次使用 -p 选项,每个软件包对应一个 -p 选项。 |
约束条件 | -c <main-category> | 如果您通过这种方式指定一个或多个类别,Monkey 将仅允许系统访问其中一个指定类别中所列的 Activity。如果没有指定任何类别,Monkey 会选择 Intent.CATEGORY_LAUNCHER 或 Intent.CATEGORY_MONKEY 类别所列的 Activity。要指定多个类别,请多次使用 -c 选项,每个类别对应一个 -c 选项。 |
调试 | --dbg-no-events | 指定后,Monkey 将初始启动到测试 Activity,但不会生成任何其他事件。为了获得最佳结果,请结合使用 -v、一个或多个软件包约束条件以及非零限制,以使 Monkey 运行 30 秒或更长时间。这提供了一个环境,您可以在其中监控应用调用的软件包转换操作。 |
调试 | --hprof | 如果设置此选项,则会在 Monkey 事件序列之前和之后立即生成分析报告。这将在 data/misc 下生成大型(约为 5Mb)文件,因此请谨慎使用。如需了解如何分析性能剖析报告,请参阅剖析应用性能。 |
调试 | --ignore-crashes | 通常,当应用崩溃或遇到任何类型的未处理异常时,Monkey 将会停止。如果指定此选项,Monkey 会继续向系统发送事件,直到计数完成为止。 |
调试 | --ignore-timeouts | 通常,当应用遇到任何类型的超时错误(例如“应用无响应”对话框)时,Monkey 将会停止。如果指定此选项,Monkey 会继续向系统发送事件,直到计数完成为止。 |
调试 | --ignore-security-exceptions | 通常,当应用遇到任何类型的权限错误(例如,如果它尝试启动需要特定权限的 Activity)时,Monkey 将会停止。如果指定此选项,Monkey 会继续向系统发送事件,直到计数完成为止。 |
调试 | --kill-process-after-error | 通常,当 Monkey 因出错而停止运行时,出现故障的应用将保持运行状态。设置此选项后,它将会指示系统停止发生错误的进程。注意,在正常(成功)完成情况下,已启动的进程不会停止,并且设备仅会处于最终事件之后的最后状态。 |
调试 | --monitor-native-crashes | 监视并报告 Android 系统原生代码中发生的崩溃。如果设置了 --kill-process-after-error,系统将会停止。 |
调试 | --wait-dbg | 阻止 Monkey 执行,直到为其连接了调试程序。 |
使用实例
通过pm list packages
命令可以看到手机中所有的包名,可以随便找一个测试,这里使用系统计算器来测试它的包名是com.android.calculator2
执行下面的命令,来执随机行应用1000次
monkey -p com.android.calculator2 1000
//可以通过-v 来输出执行日志
monkey -p com.android.calculator2 -v -v 100
-v的个数表示日志输出的级别,最多三个,越多日志越详细来看看输出的日志
data="com.android.calculator2"
//使用monkdy工具 测试了100次
//通过-s指定seed的值可以重复跟本次操作一模一样的操作
:Monkey: seed=1582553186510 count=100
//测试的包名
:AllowPackage: com.android.calculator2
//策略
:IncludeCategory: android.intent.category.LAUNCHER
:IncludeCategory: android.intent.category.MONKEY
// Selecting main activities from category android.intent.category.LAUNCHER
// + Using main activity com.android.calculator2.Calculator (from package com.android.calculator2)
// Selecting main activities from category android.intent.category.MONKEY
// Seeded: 1582553186510
// Event percentages:
//每一种事件测试的占比,每个数组代表不同的事件类型
//
// 0: 15.0%
// 1: 10.0%
// 2: 2.0%
// 3: 15.0%
// 4: -0.0%
// 5: -0.0%
// 6: 25.0%
// 7: 15.0%
// 8: 2.0%
// 9: 2.0%
// 10: 1.0%
// 11: 13.0%
日志最开始有个输出seed=1582553186510
,通过这个值我们可以重新执行一次一模一样的当前操作adb shell monkey -s 1487572980979 -v 1000
1-11的占比代表各种事件的执行比例,比如轻触事件,手势事件,缩放事件,导航事件,屏幕旋转事件等在MonkeySourceRandom这个类中有常量表示。下面是Android 9.0源码中的数值常量。
public static final int FACTOR_TOUCH = 0; //轻触
public static final int FACTOR_MOTION = 1; //滑动
public static final int FACTOR_PINCHZOOM = 2; //缩放
public static final int FACTOR_TRACKBALL = 3; //轨迹球
public static final int FACTOR_ROTATION = 4; //旋转
public static final int FACTOR_PERMISSION = 5; //权限
public static final int FACTOR_NAV = 6; //基本导航 上下左右键等
public static final int FACTOR_MAJORNAV = 7; //主要导航(一般会导致UI变化) 回退键 菜单键等
public static final int FACTOR_SYSOPS = 8; //系统事件
public static final int FACTOR_APPSWITCH = 9; //activity启动事件
public static final int FACTOR_FLIP = 10; //键盘翻转
public static final int FACTOR_ANYTHING = 11; //其他事件
如果执行过程中发生了崩溃,Monkey会停在崩溃的地方,使用--ignore-crashes
可以在崩溃的时候继续执行后序操作adb shell monkey —ignore-crashes 1000
。
程序ANR对于andorid应用来说是一个比较严重的问题,Monkey在执行中遇到ANR的时候会停止,执定--ignore-timeouts
参数可以让monkey继续执行adb shell monkey --ignore-timeouts 1000
。
使用>
符号将日志输出到特定的文件中查看比如adb shell monkey —ignore-crashes 1000>d:\monkey.txt
,此文件中会告诉我们那个地方出了问题,具体的错误日志可以通过adb bugreport
命令将运行日志导出来查看更详细的信息
//6.0及以下设备
adb bugreport > bugreport.txt
//7.0及以上设备
adb bugreport bugreport.zip
Monkey 脚本
有时候我们不想让它随机执行,通过脚本可以让测试按照我们自定义的流程来执行。使用-f参数就可以执行Monkey的脚本了adb shell monkey -f <script> 1
Monkey脚本的主要命令:
- DispatchPointer(downtime,eventTime,action,x,y,xpressure,size,metastate,xPrecision,yPrecision,device,edgeFlags):手势操作,相当于手指按到某个位置。参数x,y是手指按下的坐标位置,坐标位置可以通过DDMS中的工具UI Automator来获取,位置在sdk/tools/monitor中
- DispatchPress[keycode] 按下系统的某个固定的按键,比如home键,back键等,在官网KeyEvent这个类中有对每种keycode含义的详细介绍。
- LaunchActivity(pkg_name, cl_name): 用来启动应用 参数是 包名+类名
- UserWait:让脚本暂停一段时间
- UserWait(sleepTime):指定睡眠时间
- RotateScreen(rotationDegree, persist):参数是旋转角度+旋转后是否停在当前位置。0代表0度 1代表90度 2代表180度 3代表 270度;第二个参数 0表示旋转后恢复,非0则表示固定不变
- Tap(x, y,tapDuration):单击时间 x y 是点击屏幕的坐标 点击的时长
- Drag(xStart, yStart, xEnd, yEnd):在屏幕上滑动参数是滑动坐标的起始点
- LongPress(): 长按2s
- ProfileWait(): 等待5s
- PressAndHold(x, y, pressDuration) :模拟长按
- PinchZoom(x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End, stepCount): 模拟缩放
- DispatchString(input): 输入字符串
- RunCmd(cmd) :执行shell命令,比如截图 screencap -p /data/temp/temp.png
- DispatchFlip(true/false) :打开或者关闭软键盘
- DeviceWakeUp() :唤醒屏幕
开始编写脚本测试系统计算器 定义一个脚本文件monkey.script
type= raw events
count= 10
speed= 1.0
start data >>
LaunchActivity(com.android.calculator2,com.android.calculator2.Calculator)
#点击 6
#使用DispatchPointer(downtime,eventTime,action,x,y,xpressure,size,metastate,xPrecision,yPrecision,device,edgeFlags)来完成
#第三个参数action 0是按下 1是抬起
#使用sdk中的uiautomatorviewer.bat工具来获取x y的坐标 sdk/tools/bin/uiautomatorviewer.bat
DispatchPointer(0,0,0,600,1200,0,0,0,0,0,0,0)
DispatchPointer(0,0,1,600,1200,0,0,0,0,0,0,0)
#等待1秒
UserWait(1000)
#点击 + 号
DispatchPress(KEYCODE_PLUS)
UserWait(1000)
#点击 9
DispatchPress(KEYCODE_9)
UserWait(1000);
#点击 =
Tap(600,1600)
UserWait(1000)
#翻转屏幕 参数0123分别代表0,90,180,270
#第二个参数 0表示旋转后恢复,非0则表示固定不变
RotateScreen(2,1)
UserWait(500)
脚本需要运行在手机上,所以先上传到手机上
adb push monkey.script /sdcard/monkey.script
执行脚本
adb shell monkey -f /sdcard/monkey.script -v -v 1
Monkey Server
Monkey Server可以让我们从电脑端直接通过命令操控手机。Monkey Server在官方文档中没有介绍,简单说明下.
- 启动Monkey Server
adb shell monkey --port 1080 &
- PC端1080端口数据转发到客户端的1080端口
adb forward tcp:1080 tcp:1080
- 连接Monkey Server并进入控制台
telnet 127.0.0.1 1080
,在这里面输入Monkey Server的命令就可以操控手机了。
Monkey Server的常用命令:
- key [down|up] keycode – 指定Keycode的按键事件(分按下、弹起)
- touch [down|up|move] x y – 指定坐标的触屏操作(分按下、弹起、移动)
- trackball dx dy – 轨迹球操作
- tap x y – 指定坐标的触屏操作
- flip [open|close] – 调用软键盘
- wake – 唤醒设备
- press keycode – 指定Keycode的按键事件
- listvar – 列出所有的系统变量
- getvar varname – 获取给定系统变量值
- quit – 退出当前连接,且不接受新的连接
- done – 退出当前连接,但可以接受新的连接
- type – 输入字符
一个一个的输入命令来控制手机太麻烦,没人愿意使用。Monkey Server也是可以编写脚本,Linux中可以直接编写shell脚本即可,Window中可以借助wscript.shell
来完成
MonkeyRunner
MonkeyRunner也是Android SDK中自带的一个黑盒测试工具,支持Pyhon和Java,可以实现Monkey无法实现的一些逻辑控制。
区别:
- Monkey是运行在设备上的,可以脱离PC,MonkeyRunner运行在PC上,往手机或模拟器上发送指令来测试。
- Monkey一般用来做一些随机性的测试,前面文章也写了,官方文档上就写了随机测试怎么用,至于编写自定义脚本还需要自己看源码,还是简单的脚本。MonkeyRunner支持条件判断,可以写出更强大的自定义测试脚本。
- MonkeyRunner可以同时运行多个测试设备,还可以将运行结果截图并跟已知的一个正确的截图做比较。
MonkeyRunner包括三大模块:
- MonkeyRunner: 提供了将monkeyrunner程序连接到模拟器或者手机设备的方法。还提供了monkeyrunner程序创建界面和显示内置帮助的方法
- MonkeyDevice: 提供了安装卸载软件,启动 Activity以及向设备发送按键或者轻触事件。
- MonkeyImage:提供了截屏,将位图转换为各种格式,比较两个MonkeyImage对象和将图片写入文件的方法。
详情:
MonkeyRunner | Android Studio | Android Developers (google.cn)
MonkeyDevice | Android Studio | Android Developers (google.cn)
MonkeyImage | Android Studio | Android Developers (google.cn)
小结
以上内容是monkey涉及的基础测试说明以及方法,使用这些工具可以有效保证我们app的质量,为用户提供优质服务.后续的UI Automator、Espresso等工具后面一一介绍说明.