Monkey稳定性测试

5 minute read

Monkey 稳定性测试 完整学习大纲


一、Monkey 测试概述

1.1 Monkey 测试的定义与起源

  • 什么是 Monkey 测试:一种伪随机的用户事件流生成工具,通过模拟用户的触摸、手势、按键等操作,对 Android 应用进行压力测试和稳定性测试。
  • 名称来源:像猴子一样随机乱点,测试应用的抗压能力和异常处理能力。
  • 开发者:Google Android 团队开发,集成在 Android SDK 中。

1.2 Monkey 测试的核心价值

  • 发现崩溃 (Crash) 和无响应 (ANR) 问题
  • 验证应用在异常输入和连续操作下的稳定性
  • 评估应用的健壮性和容错能力
  • 在压力场景下暴露内存泄漏、性能瓶颈
  • 回归测试的快速验证手段

1.3 Monkey 测试的应用场景

  • 应用发布前的压力测试
  • 竞品分析时的稳定性对比
  • 长期运行的稳定性测试
  • 多场景组合的压力测试
  • 自动化测试流水线中的稳定性检查环节

1.4 Monkey 与其他测试工具对比

特性 Monkey MonkeyRunner UI Automator Appium
测试类型 稳定性/压力测试 功能测试 功能测试 功能测试
脚本支持 Python脚本 Java/JUnit 多语言
事件控制 随机 精确控制 精确控制 精确控制
学习成本
跨应用 支持 支持 支持 支持

二、环境搭建与基础使用

2.1 环境要求

  • Android SDK:必须安装,包含在 platform-tools
  • adb 工具:Android Debug Bridge
  • 测试设备:真机或模拟器,开启 USB 调试
  • 待测应用:已安装的 APK 文件

2.2 环境检查

# 检查 adb 是否安装
adb version

# 检查设备连接
adb devices

# 查看设备上安装的应用包名
adb shell pm list packages | grep "your.app"

# 检查 Monkey 是否可用
adb shell monkey -h

2.3 第一个 Monkey 测试

# 基本语法
adb shell monkey [options] <event-count>

# 示例:对包名为 com.example.app 的应用发送 1000 个随机事件
adb shell monkey -p com.example.app 1000

2.4 测试结果解读

  • 测试成功完成:显示 Events injected: 1000
  • 应用崩溃:显示 CRASH 信息
  • 应用无响应:显示 ANR 信息
  • 其他异常:权限问题、强制关闭等

三、Monkey 参数详解

  1. 基础参数
    # 指定测试的应用包
    -p <package_name>
    # 示例:测试指定应用
    adb shell monkey -p com.example.app 1000
    
    # 测试多个应用
    adb shell monkey -p com.app1 -p com.app2 1000
    
    # 测试所有应用 (不推荐,可能造成系统异常)
    adb shell monkey 1000
    
  2. 事件类型参数
    # 指定各类型事件百分比
    # 格式:--pct-<事件类型> <百分比>
    adb shell monkey \
      --pct-touch 40 \       # 触摸事件
      --pct-motion 25 \      # 滑动事件
      --pct-trackball 5 \    # 轨迹球事件
      --pct-nav 10 \         # 导航事件
      --pct-majornav 10 \    # 主要导航事件
      --pct-syskeys 5 \      # 系统按键
      --pct-appswitch 3 \    # 应用切换
      --pct-anyevent 2 \     # 任意事件
      --pct-pinchzoom 0 \    # 双指缩放
      --pct-permission 0 \   # 权限事件
      --pct-rotation 0 \     # 屏幕旋转
      1000
    
  3. 调试参数
    # 设置随机种子 (seed)
    # 相同种子产生相同的事件序列,用于复现问题
    -s <seed>
    adb shell monkey -s 12345 1000
    
    # 设置事件延迟
    # 每个事件之间的延迟时间(毫秒)
    --throttle <milliseconds>
    adb shell monkey --throttle 500 1000
    
    # 设置超时时间
    # 在指定时间(秒)后停止测试
    --timeout <seconds>
    adb shell monkey --timeout 300 10000
    
  4. 约束参数
    # 忽略超时 (忽略ANR)
    --ignore-timeouts
    
    # 忽略崩溃 (忽略Crash)
    --ignore-crashes
    
    # 忽略安全异常
    --ignore-security-exceptions
    
    # 监控本地代码崩溃
    --monitor-native-crashes
    
    # 杀死超时进程
    --kill-process-after-error
    
  5. 高级参数
    # 设置日志级别
    -v (简单) -v -v (详细) -v -v -v (最详细)
    adb shell monkey -v -v 1000
    
    # 禁用状态栏
    --pkg-blacklist-file <file>
    # 禁用通知栏
    --pkg-whitelist-file <file>
    
    # 设置应用无响应超时时间(毫秒)
    --hprof
    

四、Monkey 事件类型详解

  1. 触摸事件 (Touch Events)
    • 事件类型--pct-touch <percent>
    • 描述:模拟用户在屏幕上的单点触摸操作
    • 包含操作:点击、长按
    • 最佳实践:一般设置为 40-50%,模拟用户最常见的操作
  2. 手势事件 (Motion Events)
    • 事件类型--pct-motion <percent>
    • 描述:模拟用户在屏幕上滑动、拖拽的操作
    • 包含操作:上下左右滑动、任意方向滑动
    • 最佳实践:设置为 20-30%,测试列表滚动、页面切换
  3. 轨迹球事件 (Trackball Events)
    • 事件类型--pct-trackball <percent>
    • 描述:模拟轨迹球操作,已很少使用
    • 最佳实践:现代设备可设为 0 或较小值
  4. 基本导航事件 (Nav Events)
    • 事件类型--pct-nav <percent>
    • 描述:模拟导航设备的基本操作
    • 包含操作:上、下、左、右方向键
    • 最佳实践:设置为 5-10%
  5. 主要导航事件 (Major Nav Events)
    • 事件类型--pct-majornav <percent>
    • 描述:模拟导航设备的主要操作
    • 包含操作:返回键、菜单键
    • 最佳实践:设置为 5-10%
  6. 系统按键事件 (Syskeys)
    • 事件类型--pct-syskeys <percent>
    • 描述:模拟系统按键操作
    • 包含操作:Home键、音量键、电源键
    • 最佳实践:设置为 5-10%
  7. 应用切换事件 (Appswitch)
    • 事件类型--pct-appswitch <percent>
    • 描述:模拟应用切换操作
    • 最佳实践:设置为 5-10%,测试应用前后台切换
  8. 其他事件类型
    • 缩放事件--pct-pinchzoom
    • 权限事件--pct-permission
    • 旋转事件--pct-rotation
    • 任意事件--pct-anyevent

五、Monkey 脚本编写

5.1 Monkey 脚本基础

  • 脚本文件格式:纯文本文件,每行一个命令
  • 脚本作用:定制化的事件序列
  • 脚本优势:可重复执行、可版本控制

5.2 脚本事件语法

# 基本格式
<command>; <delay>; <component>; <x>; <y>;

# 示例
DispatchPointer(0,0,0,500,500,0,0,0,0,0,0,0);
UserWait(2000);
DispatchPress(KEYCODE_BACK);

5.3 常用脚本命令

# 点击事件
DispatchPointer(downTime,eventTime,action,x,y,pressure,size,metaState,xPrecision,yPrecision,deviceId,edgeFlags);
DispatchPointer(0,0,0,100,200,0,0,0,0,0,0,0);  # 在(100,200)位置点击

# 按键事件
DispatchPress(keycode);
DispatchPress(KEYCODE_HOME);  # 按Home键
DispatchPress(KEYCODE_BACK);  # 按返回键

# 等待
UserWait(milliseconds);
UserWait(2000);  # 等待2秒

# 输入文本
DispatchString(input);
DispatchString("Hello World");

# 启动Activity
LaunchActivity(pkg, clz);
LaunchActivity(com.example.app, com.example.app.MainActivity);

5.4 脚本示例

# 保存为 monkey_script.txt
# 启动应用
LaunchActivity(com.example.app, com.example.app.MainActivity);
UserWait(2000);

# 点击登录按钮
DispatchPointer(0,0,0,300,500,0,0,0,0,0,0,0);
UserWait(1000);

# 输入用户名
DispatchString("testuser");
UserWait(500);

# 按返回键
DispatchPress(KEYCODE_BACK);
UserWait(1000);

# 执行脚本
adb shell monkey -f /sdcard/monkey_script.txt 1

六、Monkey 测试策略

6.1 测试场景设计

  • 冒烟测试:少量事件快速验证
  • 稳定性测试:长时间大量事件
  • 压力测试:高频率事件
  • 兼容性测试:不同设备、系统版本
  • 回归测试:每次发布前执行

6.2 事件比例配置策略

# 推荐配置 - 模拟真实用户
触摸事件: 40%
手势事件: 25%
基本导航: 10%
主要导航: 10%
系统按键: 5%
应用切换: 5%
其他: 5%

# 游戏应用配置
触摸事件: 60%
手势事件: 20%
系统按键: 10%
其他: 10%

# 工具类应用配置
触摸事件: 30%
手势事件: 20%
基本导航: 20%
主要导航: 20%
系统按键: 5%
应用切换: 5%

6.3 测试时长与次数规划

  • 快速测试:1000-5000 个事件
  • 标准测试:10000-50000 个事件
  • 深度测试:100000+ 个事件
  • 时长建议:5分钟 - 24小时不等

6.4 多设备并行测试

# 获取设备列表
devices=$(adb devices | grep -v "List" | awk '{print $1}')

# 并行执行
for device in $devices; do
  adb -s $device shell monkey -p com.example.app 10000 &
done

# 等待所有测试完成
wait

七、测试结果分析

7.1 日志级别与输出

# 不同详细级别的日志
adb shell monkey -p com.example.app -v 1000      # Level 0
adb shell monkey -p com.example.app -v -v 1000   # Level 1
adb shell monkey -p com.example.app -v -v -v 1000 # Level 2

# 输出到文件
adb shell monkey -p com.example.app 1000 > monkey_log.txt

7.2 关键信息提取

# 成功完成
Events injected: 1000
# 发送种子
:Sending rotation degree=0, persist=false
# 事件统计
:Monkey: seed=12345 count=1000
# 异常信息
// CRASH: com.example.app (pid 12345)
// ANR: com.example.app (pid 12345)

7.3 崩溃分析

  • Java Crash:Java层崩溃
  • Native Crash:Native层崩溃
  • ANR:应用无响应
  • Force Close:强制关闭

7.4 日志分析工具

# 过滤崩溃信息
grep -i "crash" monkey_log.txt
grep -i "anr" monkey_log.txt
grep -i "exception" monkey_log.txt

# 统计事件类型
grep "Sending" monkey_log.txt | wc -l

# 提取错误堆栈
grep -A 20 "FATAL EXCEPTION" monkey_log.txt

7.5 性能监控

# 监控CPU
adb shell top -d 1 | grep com.example.app

# 监控内存
adb shell dumpsys meminfo com.example.app

# 监控电池
adb shell dumpsys battery

八、高级技巧与最佳实践

  1. 避免误操作系统应用
    # 创建白名单
    echo "com.example.app" > /sdcard/whitelist.txt
    adb push whitelist.txt /sdcard/
    
    # 创建黑名单
    echo "com.android.settings" > /sdcard/blacklist.txt
    echo "com.android.phone" >> /sdcard/blacklist.txt
    adb push blacklist.txt /sdcard/
    
  2. 结合其他工具使用
    # 结合logcat收集日志
    adb logcat -c
    adb logcat -v time > app_log.txt &
    adb shell monkey -p com.example.app 10000
    kill %1
    
    # 结合systrace分析性能
    python systrace.py -a com.example.app -o trace.html monkey
    
  3. 自动化测试集成
    #!/usr/bin/env python3
    import subprocess
    import time
    import os
    
    def run_monkey_test(package_name, event_count, seed=None):
        """执行Monkey测试"""
        cmd = ["adb", "shell", "monkey", "-p", package_name]
            
        if seed:
            cmd.extend(["-s", str(seed)])
            
        cmd.extend(["-v", "-v", "--throttle", "100", "--ignore-crashes", 
                    "--ignore-timeouts", str(event_count)])
            
        log_file = f"monkey_{package_name}_{int(time.time())}.log"
            
        with open(log_file, "w") as f:
            result = subprocess.run(cmd, stdout=f, stderr=subprocess.STDOUT, 
                                  text=True, timeout=3600)
            
        return result.returncode, log_file
    
    def analyze_log(log_file):
        """分析日志文件"""
        with open(log_file, "r") as f:
            content = f.read()
            
        if "CRASH" in content:
            return "CRASH"
        elif "ANR" in content:
            return "ANR"
        else:
            return "PASS"
    
    if __name__ == "__main__":
        package = "com.example.app"
        for i in range(10):  # 执行10轮测试
            print(f"第{i+1}轮测试开始...")
            retcode, logfile = run_monkey_test(package, 5000, seed=i*1000)
            result = analyze_log(logfile)
            print(f"第{i+1}轮测试结果: {result}")
    
  4. 测试报告生成
    import json
    from datetime import datetime
    
    def generate_report(test_results):
        """生成测试报告"""
        report = {
            "project": "Monkey Test Report",
            "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "summary": {
                "total_tests": len(test_results),
                "pass_count": sum(1 for r in test_results if r["result"] == "PASS"),
                "crash_count": sum(1 for r in test_results if r["result"] == "CRASH"),
                "anr_count": sum(1 for r in test_results if r["result"] == "ANR"),
            },
            "details": test_results
        }
            
        with open("monkey_report.json", "w") as f:
            json.dump(report, f, indent=2, ensure_ascii=False)
            
        return report
    
  5. 最佳实践总结
    • 设置合适的种子:便于问题复现
    • 合理的事件比例:模拟真实用户行为
    • 添加适当延迟:避免事件过快
    • 忽略非关键异常:专注于稳定性测试
    • 监控系统资源:及时发现性能问题
    • 保存完整日志:便于问题分析
    • 多轮次测试:提高问题发现率
    • 版本对比测试:验证修复效果

九、常见问题与解决方案

  1. 权限问题
    # 错误:java.lang.SecurityException: Permission Denial
    # 解决方案:
    # 1. 添加忽略安全异常参数
    adb shell monkey --ignore-security-exceptions ...
    
    # 2. 授予必要权限
    adb shell pm grant com.example.app android.permission.xxx
    
  2. 设备无响应
    # 设备卡死时强制重启
    adb reboot
    
    # 杀死Monkey进程
    adb shell ps | grep monkey
    adb shell kill <pid>
    
  3. 测试中断
    # 网络断开重连
    adb kill-server
    adb start-server
    adb devices
    
    # 应用崩溃后继续测试
    adb shell monkey --ignore-crashes ...
    
  4. 结果不一致
    # 相同种子产生不同结果
    # 原因:设备状态、应用状态不同
    # 解决方案:测试前重置应用状态
    adb shell pm clear com.example.app
    

十、扩展与进阶

  1. Monkey 与其他工具结合
    • Monkey + Appium:混合测试框架
    • Monkey + Jenkins:持续集成
    • Monkey + Python:自动化测试框架
    • Monkey + Shell:批量化测试
  2. 自定义 Monkey
    • 修改源码:Android开源项目
    • 添加新事件类型
    • 自定义事件分布
    • 集成业务逻辑
  3. 云测试平台
    • Firebase Test Lab
    • AWS Device Farm
    • 百度MTC
    • Testin
  4. 机器学习优化
    • 智能事件生成
    • 异常模式识别
    • 自适应测试策略
    • 预测性分析

十一、学习资源

11.1 官方文档

  • Android Developers:Monkey 官方文档
  • Android SDK:源代码和工具
  • GitHub:开源项目和示例

11.2 在线教程

  • Google Testing Blog
  • Android Testing Guide
  • 各大技术社区专栏

11.3 书籍推荐

  • 《Android 测试之道》
  • 《移动App测试实战》
  • 《Google软件测试之道》

11.4 实践项目

  1. 构建自动化 Monkey 测试框架
  2. 实现 Monkey 测试结果分析平台
  3. 开发 Monkey 测试报告系统
  4. 集成到 CI/CD 流水线
  5. 多设备集群测试系统

11.5 社区资源

  • Stack Overflow
  • GitHub Issues
  • Android Testing Community
  • 各大公司技术博客