Android自动化测试有很多方式,常见的包括MonkeyRunner,Robotium,SL4A,Java Instrumentation,Shell脚本等(随机点击的Monkey测试太过低级不在此列)。这篇先介绍Shell脚本测试,我猜这可能是最不常用的一种,但因为API很少,学习成本较低,如果对Shell较熟悉的同学就灰常合适:)
了解手机上的设备
手机上有很多输入设备,这些设备的编号每个手机都不同,因此我们需要首先了解这个手机上都有哪些输入设备,下面以我的NexusS为例:
> adb shell cat /proc/bus/input/devices
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="mxt224_ts_input"
P: Phys=
S: Sysfs=/devices/virtual/input/input0
U: Uniq=
H: Handlers=event0
B: EV=9
B: ABS=2650000 0
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="gyro"
P: Phys=
S: Sysfs=/devices/virtual/input/input1
U: Uniq=
H: Handlers=event1
B: EV=5
B: REL=38
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="herring-keypad"
P: Phys=
S: Sysfs=/devices/virtual/input/input2
U: Uniq=
H: Handlers=event2 keychord
B: EV=3
B: KEY=1c0000 0 0 0
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="proximity"
P: Phys=
S: Sysfs=/devices/virtual/input/input3
U: Uniq=
H: Handlers=event3
B: EV=9
B: ABS=2000000
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="lightsensor-level"
P: Phys=
S: Sysfs=/devices/virtual/input/input4
U: Uniq=
H: Handlers=event4
B: EV=9
B: ABS=100 0
I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="compass"
P: Phys=
S: Sysfs=/devices/virtual/input/input5
U: Uniq=
H: Handlers=event5
B: EV=5
B: REL=3ff
以上高亮部分显示了这台手机上的6个输入设备,如下:
设备名称
说明
HANDLER
mxt224_ts_input
屏幕触摸输入
event0
Gyro
陀螺仪
event1
herring-keypad
键盘
event2
proximity
近距离感应器(脸颊感应)
event3
lightsensor-level
光感应器
event4
compass
定位仪
event5
注意:每台设备上的输入设备分布和名称都可能不一样
选择一个合适的设备来进行我们的输入测试,对于大多数情况来说,一般只需要用到键盘和屏幕触摸输入,下面我们以屏幕触摸输入为例。将用到两个对应的命令:getevent和sendevent,顾名思义,一个是获取事件,另一个则是发送模拟事件。
用getevent了解设备运作
首先我们随便执行一条getevent来监听Handler event0(event0为屏幕事件):
> adb shell getevent /dev/input/event0
然后点击一下桌面上某一个app(使其进入),会看到类似以下内容:
0003 0035 0000008b
0003 0036 000002c0
0003 0030 00000044
0003 0032 00000004
0003 0039 00000000
0000 0002 00000000
0000 0000 00000000
0003 0035 0000008b
0003 0036 000002c0
0003 0030 00000000
0003 0032 00000001
0003 0039 00000000
0000 0002 00000000
0000 0000 00000000
以上内容的格式为:[type] [code] [value]
但这些type和code究竟是什么意思呢?输入以下指令
> adb shell getevent -p /dev/input/event0
add device 1: /dev/input/event0
name: "mxt224_ts_input"
events:
SYN (0000): 0000 0003
ABS (0003): 0030 value 0, min 0, max 255, fuzz 0 flat 0
0032 value 0, min 0, max 30, fuzz 0 flat 0
0035 value 0, min 0, max 1023, fuzz 0 flat 0
0036 value 0, min 0, max 950, fuzz 0 flat 0
0039 value 0, min 0, max 4, fuzz 0 flat 0
这个依然有点晦涩,大意为:
type类型可能出现两种,分别是 0000 代表 SYN,0003 代表 ABS
ABS type下的code 类型可能出现若干种,包括 0030,0032,0035,0036,0039
这五种code的意义可以参见 /frameworks/base/include/ui/EventHub.h
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device (finger, pen, ...) */
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
因此刚刚getevent获取到的内容大致可以做如下翻译:
0003 0035 0000008b // x轴0x8b的位置
0003 0036 000002c0 // y轴0x2c0的位置
0003 0030 00000044 // 触摸椭圆的长轴为0x44
0003 0032 00000004 // ??椭圆的长轴为0x4
0003 0039 00000000 // Tracking ID为0
0000 0002 00000000 // SYN
0000 0000 00000000 // SYN
---- 昏割线 ----
0003 0035 0000008b
0003 0036 000002c0
0003 0030 00000000 // 触摸椭圆的长轴为0(表示离开屏幕了)
0003 0032 00000001
0003 0039 00000000
0000 0002 00000000
0000 0000 00000000
有了以上知识作为基础,我们就可以开始着手编写我们自己的自动化测试脚本了
关于getevent的使用细节可以参见 Android官网上的一篇文章 ,不过里面写的东西基本是在扯蛋。
使用sendevent模拟事件
先看看sendevent的使用方法:
> adb shell sendevent –h
use: sendevent device type code value
先做个简单的测试,我们回到桌面准备模拟一遍刚才点击的动作,如果成功的话会进入刚刚那个app。利用sendevent编写模拟事件脚本x.sh:
#!/system/bin/sh
sendevent /dev/input/event0 3 $((0x35)) $((0x8b))
sendevent /dev/input/event0 3 $((0x36)) $((0x2c0))
sendevent /dev/input/event0 3 $((0x30)) $((0x44))
sendevent /dev/input/event0 3 $((0x32)) $((0x04))
sendevent /dev/input/event0 3 $((0x39)) $((0x00))
sendevent /dev/input/event0 0 $((0x02)) $((0x00))
sendevent /dev/input/event0 0 $((0x00)) $((0x00))
sendevent /dev/input/event0 3 $((0x35)) $((0x8b))
sendevent /dev/input/event0 3 $((0x36)) $((0x2c0))
sendevent /dev/input/event0 3 $((0x30)) $((0x00))
sendevent /dev/input/event0 3 $((0x32)) $((0x04))
sendevent /dev/input/event0 3 $((0x39)) $((0x00))
sendevent /dev/input/event0 0 $((0x02)) $((0x00))
sendevent /dev/input/event0 0 $((0x00)) $((0x00))
以上高亮处表示,在同一个位置先点击后松开。现在执行
> adb push x.sh /sdcard/
> adb shell sh /sdcard/x.sh
观察手机,发现之前的app被点击了
这样我们成功的模拟了一个最简单的点击,如果想模拟其他的动作,可以尝试自己动手观察一下设备接收到的事件,再重复出来即可
优化
本来到这里应该已经完了,但作为一位懒惰的程序员,是无法接受平时写自动化测试脚本需要编写如此多如此重复的代码的,于是我总结了一下,抽象了一个小库,用于模拟屏幕上各种基础的动作
#!/system/bin/sh
# Script to execute automatical test.
# By using: adb shell sendevent [device] [type] [code] [value]
#
# @author GuoLin
# Click on a point
click()
{
press $1 $2
release $1 $2
}
# Long click on a point
longclick()
{
press $1 $2
press $1 $2
sleep 1
}
# Fling from a point to another
fling()
{
move $1 $2 $3 $4
release $3 $4
}
# Drag and drop
dad()
{
longclick $1 $2
move $1 $2 $3 $4
release $3 $4
}
# Move from a point to another
move()
{
for i in 1 2 3 4;
do
x=$(( ($3 - $1) * $i / 3 + $1 ))
y=$(( ($4 - $2) * $i / 3 + $2 ))
press $x $y
done;
}
# Press a point
press()
{
sendevent $EVENT 3 $((0x35)) $1
sendevent $EVENT 3 $((0x36)) $2
sendevent $EVENT 3 $((0x30)) $((0x44))
sendevent $EVENT 3 $((0x32)) $((0x04))
sendevent $EVENT 3 $((0x39)) $((0x00))
sendevent $EVENT 0 $((0x02)) $((0x00))
sendevent $EVENT 0 $((0x00)) $((0x00))
}
# Release on a point
release()
{
sendevent $EVENT 3 $((0x35)) $1
sendevent $EVENT 3 $((0x36)) $2
sendevent $EVENT 3 $((0x30)) $((0x00))
sendevent $EVENT 3 $((0x32)) $((0x04))
sendevent $EVENT 3 $((0x39)) $((0x00))
sendevent $EVENT 0 $((0x02)) $((0x00))
sendevent $EVENT 0 $((0x00)) $((0x00))
}
# Samples
# Click on icon on cell 1,4
#click $((0x8b)) $((0x2c0))
# Scroll screen
#fling $((0x8b)) $((0x2c0)) $((0x222)) $((0x2c0))
# Drag and drop
#dad $((0x8b)) $((0x2c0)) $((0x8b)) $((0x200))
最底部的Samples例举了几种常用操作。