Android自动化测试工具MonkeyRunner实战
简介:MonkeyRunner是Android SDK中的自动化测试工具,支持通过Python脚本控制设备或模拟器,执行如点击、滑动、文本输入、截图等操作。适用于应用自动化测试及批量任务处理。本资源包包含多个示例脚本,如录制回放、帮助文档生成、设备控制等,帮助开发者快速掌握MonkeyRunner的使用方法与核心API,提升测试效率与自动化能力。
1. MonkeyRunner简介与安装配置
MonkeyRunner是Android SDK提供的一个基于Python的自动化测试工具,专为Android平台设计,支持对设备进行功能测试、回归测试和UI行为模拟。它通过Java服务器与Android设备通信,提供MonkeyDevice、MonkeyImage等核心类,实现设备控制、图像识别和事件模拟等功能。
要使用MonkeyRunner,首先需配置Java环境与Android SDK,并将 tools 和 platform-tools 路径加入系统环境变量。随后,安装Python 2.7(官方推荐版本),并确保可执行 monkeyrunner 命令。最后通过USB调试模式连接Android设备,使用 adb devices 确认设备识别状态,即可开始编写测试脚本。
本章将为读者奠定MonkeyRunner的使用基础,为后续章节的设备操作、图像识别与自动化测试流程整合做好准备。
2. MonkeyDevice类操作详解
MonkeyDevice类是MonkeyRunner中用于与Android设备交互的核心类,提供了丰富的API来执行设备操作,如启动应用、发送事件、获取设备信息等。掌握MonkeyDevice的使用,是编写高效自动化测试脚本的关键。本章将从基础操作、事件模拟到异常处理与设备管理,系统讲解MonkeyDevice的各类方法及其使用技巧。
2.1 MonkeyDevice的基本操作
MonkeyDevice的基本操作包括设备连接、启动与关闭应用、获取设备信息等,是自动化脚本执行的起点。
2.1.1 连接设备与获取设备实例
在使用MonkeyRunner进行测试之前,必须确保设备已连接到计算机并处于可调试状态。通过 MonkeyRunner.waitForConnection() 方法可以获取设备实例。
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
# 等待设备连接,最长等待时间10秒
device = MonkeyRunner.waitForConnection(10)
if device:
print("设备连接成功")
else:
print("设备连接失败")
代码逐行解读:
- 第1行:导入MonkeyRunner和MonkeyDevice模块。
- 第4行:调用
waitForConnection()方法等待设备连接,参数10表示最长等待时间为10秒。 - 第6行:判断是否成功获取设备实例,若成功则输出“设备连接成功”。
设备连接方式:
| 连接方式 | 说明 |
|---|---|
| USB连接 | 最常用,需启用USB调试模式 |
| Wi-Fi连接 | 需先通过USB连接,再切换到TCP/IP模式 |
| 模拟器连接 | 通过adb自动识别模拟器 |
提示 :可通过
adb devices命令查看当前连接的设备列表。
2.1.2 启动和关闭应用
获取设备实例后,可以使用 startActivity() 和 press() 方法启动应用,使用 shell() 方法执行adb命令关闭应用。
# 启动应用
device.startActivity(component="com.example.app/.MainActivity")
# 延迟2秒
MonkeyRunner.sleep(2)
# 关闭应用(通过adb shell am命令)
device.shell("am force-stop com.example.app")
代码说明:
-
startActivity()用于启动指定包名和Activity的应用。 -
MonkeyRunner.sleep(2)表示等待2秒,确保应用启动完成。 -
shell()方法执行adb命令,am force-stop用于强制停止应用。
启动方式对比:
| 启动方式 | 方法 | 说明 |
|---|---|---|
| startActivity | device.startActivity() | 启动指定组件 |
| shell(am start) | device.shell("am start ...") | 更灵活,可传递Intent参数 |
2.1.3 获取设备信息与状态
MonkeyDevice提供多种方法获取设备信息,如型号、系统版本、屏幕分辨率等。
# 获取设备属性
device_prop = device.getProperty('build.model')
print(f"设备型号: {device_prop}")
# 获取屏幕截图
snapshot = device.takeSnapshot()
snapshot.writeToFile('screen.png', 'png')
# 获取设备状态(如充电、熄屏等)
status = device.shell("dumpsys power | grep 'mPowerState='")
print(f"设备电源状态: {status}")
输出示例:
设备型号: Pixel 5
设备电源状态: mPowerState=0x1
常用设备信息获取方式:
| 信息类型 | 方法/命令 | 说明 |
|---|---|---|
| 设备型号 | device.getProperty('build.model') | 获取设备型号 |
| Android版本 | device.getProperty('build.version.release') | 获取系统版本 |
| 屏幕截图 | device.takeSnapshot() | 获取当前屏幕图像 |
| 电源状态 | device.shell("dumpsys power") | 查看电源管理状态 |
2.2 MonkeyDevice的事件模拟
事件模拟是MonkeyRunner的核心功能之一,支持点击、滑动、输入、键盘事件等操作,能够模拟用户行为进行自动化测试。
2.2.1 模拟点击、滑动、输入等事件
MonkeyDevice提供了 touch() 、 drag() 、 type() 等方法来模拟用户操作。
# 模拟点击坐标 (500, 1000)
device.touch(500, 1000, MonkeyDevice.DOWN_AND_UP)
# 模拟从(200, 1500)滑动到(800, 1500)
device.drag((200, 1500), (800, 1500), 0.5, 10)
# 模拟输入文本
device.type("Hello, MonkeyRunner!")
事件说明:
-
touch(x, y, type):模拟点击事件,DOWN_AND_UP表示按下并释放。 -
drag(start, end, duration, steps):模拟滑动,duration为滑动总时间(秒),steps为分段数。 -
type(text):模拟键盘输入,逐字符输入。
2.2.2 多点触控与键盘事件处理
MonkeyDevice支持多点触控和键盘事件,通过 press() 和 keyEvent() 方法实现。
# 模拟按下Home键
device.press("KEYCODE_HOME", MonkeyDevice.DOWN_AND_UP)
# 模拟多点触控(双指放大)
device.touch(300, 1000, MonkeyDevice.DOWN)
device.touch(700, 1000, MonkeyDevice.DOWN)
MonkeyRunner.sleep(0.5)
device.touch(300, 1000, MonkeyDevice.UP)
device.touch(700, 1000, MonkeyDevice.UP)
键盘事件对照表:
| 按键名称 | KeyCode | 说明 |
|---|---|---|
| Home | KEYCODE_HOME | 主页键 |
| Back | KEYCODE_BACK | 返回键 |
| Menu | KEYCODE_MENU | 菜单键 |
| Power | KEYCODE_POWER | 电源键 |
2.2.3 事件延迟与执行顺序控制
合理控制事件之间的延迟可以提高脚本的稳定性。MonkeyRunner提供了 sleep() 方法用于控制延迟。
# 顺序执行多个事件
device.touch(100, 500, MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(1) # 延迟1秒
device.touch(200, 500, MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(0.5)
device.touch(300, 500, MonkeyDevice.DOWN_AND_UP)
事件执行流程图:
graph TD
A[开始] --> B[点击(100,500)]
B --> C[延迟1秒]
C --> D[点击(200,500)]
D --> E[延迟0.5秒]
E --> F[点击(300,500)]
F --> G[结束]
2.3 MonkeyDevice的异常处理与设备管理
在实际测试中,可能会遇到设备连接中断、操作失败等问题,因此需要对异常进行捕获和处理。
2.3.1 常见连接与操作错误处理
常见的错误包括设备未连接、操作超时、命令执行失败等。可以通过 try-except 结构进行异常捕获。
try:
device = MonkeyRunner.waitForConnection(5)
if not device:
raise Exception("设备连接失败")
device.touch(1000, 2000, MonkeyDevice.DOWN_AND_UP)
except Exception as e:
print(f"发生异常: {e}")
常见异常类型:
| 异常类型 | 触发场景 | 说明 |
|---|---|---|
TimeoutError | waitForConnection超时 | 等待设备连接超时 |
IOException | 设备通信中断 | ADB连接异常 |
RuntimeException | 方法调用失败 | 如无效坐标、命令执行失败 |
2.3.2 多设备并发操作与切换
当多个设备连接时,可以通过 MonkeyRunner.waitForConnection() 带参数方式选择设备。
# 获取指定序列号的设备
device1 = MonkeyRunner.waitForConnection(5, "emulator-5554")
device2 = MonkeyRunner.waitForConnection(5, "emulator-5556")
# 分别执行操作
device1.touch(500, 1000, MonkeyDevice.DOWN_AND_UP)
device2.touch(500, 1000, MonkeyDevice.DOWN_AND_UP)
设备切换流程图:
graph LR
A[开始]
A --> B[等待设备1连接]
B --> C[等待设备2连接]
C --> D[设备1点击操作]
C --> E[设备2点击操作]
D --> F[结束]
E --> F
2.3.3 脚本中断与恢复机制
脚本执行过程中可能会因异常或用户中断而终止,为了保证设备状态可恢复,建议加入清理逻辑。
import sys
try:
device = MonkeyRunner.waitForConnection(10)
print("开始执行操作...")
device.touch(500, 1000, MonkeyDevice.DOWN_AND_UP)
except KeyboardInterrupt:
print("检测到中断信号,执行清理操作")
device.shell("am force-stop com.example.app")
sys.exit(0)
脚本中断恢复策略:
| 情况 | 恢复方式 | 说明 |
|---|---|---|
| 异常退出 | try-except捕获 | 可记录日志、清理资源 |
| 用户中断 | KeyboardInterrupt | 可执行设备清理操作 |
| 自动重启 | 结合外部脚本 | 通过shell脚本实现重试机制 |
本章详细讲解了MonkeyDevice类的核心操作,包括设备连接、应用控制、事件模拟、异常处理等。通过本章内容,读者应能够熟练使用MonkeyDevice编写稳定、高效的自动化测试脚本,为后续章节中更复杂的测试流程打下坚实基础。
3. MonkeyImage图像识别与截图比对
MonkeyImage类是MonkeyRunner工具链中用于处理图像数据的核心组件。它不仅可以实现设备界面的截图操作,还能进行图像的像素级访问、裁剪、缩放和比对,为自动化测试提供了直观的界面验证手段。在实际测试过程中,图像识别技术常用于判断UI元素是否加载成功、验证界面状态是否符合预期、检测界面渲染异常等场景。本章将从基础操作入手,深入解析图像比对的实现原理,并结合实际测试案例展示其应用场景。
3.1 MonkeyImage的基本操作
MonkeyImage类提供了丰富的图像处理功能,包括截图、显示、裁剪、缩放和像素访问等操作。这些功能为自动化测试脚本的编写提供了强有力的支持,特别是在需要验证UI状态的场景中尤为关键。
3.1.1 截图保存与图像显示
在MonkeyRunner中,可以通过MonkeyDevice对象获取当前设备屏幕的截图,返回一个MonkeyImage对象。以下是截图保存的基本示例:
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
# 连接设备
device = MonkeyRunner.waitForConnection()
# 获取当前屏幕截图
image = device.takeSnapshot()
# 保存截图到本地
image.writeToFile('/tmp/screenshot.png', 'png')
# 显示图像(仅在支持的环境中有效)
image.writeToFile('/tmp/screenshot.png', 'png')
代码逻辑分析:
-
MonkeyRunner.waitForConnection():等待设备连接,返回一个MonkeyDevice对象。 -
device.takeSnapshot():获取当前设备屏幕的截图,返回MonkeyImage对象。 -
writeToFile():将图像保存为指定格式的文件,第一个参数是文件路径,第二个是图像格式,如png或jpg。
参数说明:
-file:图像保存路径,必须为字符串。
-format:图像格式,通常使用png,因为它支持透明通道,图像质量高。
3.1.2 图像裁剪与缩放处理
MonkeyImage类支持对图像进行裁剪和缩放操作,适用于仅需比对界面某一部分的场景。例如,我们只关心某个按钮区域是否正确显示。
# 获取截图
image = device.takeSnapshot()
# 裁剪图像(x, y, width, height)
cropped_image = image.getSubImage((100, 200, 300, 400))
# 缩放图像(宽度, 高度)
resized_image = cropped_image.resize((150, 200), 1)
# 保存裁剪后的图像
cropped_image.writeToFile('/tmp/cropped.png', 'png')
resized_image.writeToFile('/tmp/resized.png', 'png')
代码逻辑分析:
-
getSubImage():从原始图像中裁剪出指定区域。参数是一个四元组(x, y, width, height),表示从坐标 (x, y) 开始,裁剪宽度为 width、高度为 height 的矩形区域。 -
resize():对图像进行缩放,第一个参数是目标尺寸(width, height),第二个参数是缩放质量(通常为1)。
参数说明:
-x/y:裁剪区域左上角坐标。
-width/height:裁剪区域或缩放目标的宽高。
-quality:缩放质量,1表示最优。
3.1.3 图像像素级别的访问
MonkeyImage支持对图像中任意像素点的颜色值进行访问,这在某些图像比对场景中非常有用,例如判断某个按钮的颜色是否发生变化。
# 获取截图
image = device.takeSnapshot()
# 获取某一点的像素颜色值(x, y)
color = image.getRawPixel(100, 200)
# 打印颜色值(ARGB格式)
print(f"Color at (100, 200): {color}")
代码逻辑分析:
-
getRawPixel(x, y):返回指定坐标的像素颜色值,以整数形式表示 ARGB 值(Alpha, Red, Green, Blue)。 - 可以将该颜色值与预期值进行比较,用于检测UI状态是否变化。
参数说明:
-x/y:像素点的坐标,必须为整数。
- 返回值是一个整数,表示ARGB颜色值。
3.2 图像比对技术与实现
图像比对是自动化测试中验证界面状态的重要手段。MonkeyImage类提供了基于像素值的图像比对方法,同时也支持通过设置相似度阈值来判断图像是否一致。
3.2.1 基于像素值的图像比对方法
最直接的图像比对方式是逐像素比对两个图像是否完全一致。以下是一个示例:
# 获取两张截图
image1 = device.takeSnapshot()
image2 = device.takeSnapshot()
# 比较图像是否完全一致
if image1.sameAs(image2, 1.0):
print("Images are identical.")
else:
print("Images differ.")
代码逻辑分析:
-
sameAs(otherImage, percent):比较两个图像是否一致。percent参数表示相似度阈值,1.0 表示完全一致,0.9 表示允许10%的像素差异。
参数说明:
-otherImage:要比较的另一个MonkeyImage对象。
-percent:相似度阈值,取值范围为0.0~1.0。
3.2.2 使用相似度阈值判断图像一致性
在实际测试中,由于设备分辨率、屏幕刷新率等因素,完全一致的图像比对往往不现实。因此,使用相似度阈值进行判断更为合理。
# 获取截图
image1 = device.takeSnapshot()
# 模拟操作后再次截图
device.touch(500, 800, 'DOWN_AND_UP')
image2 = device.takeSnapshot()
# 设置相似度阈值为0.95(允许5%的差异)
if image1.sameAs(image2, 0.95):
print("界面状态未发生变化。")
else:
print("界面状态发生变化,可能存在异常。")
代码逻辑分析:
- 通过设置
percent=0.95允许一定比例的像素差异,从而避免因轻微渲染差异导致误判。
参数说明:
- 通常设置为0.95或0.98,适用于大多数界面状态验证。
3.2.3 实现动态截图与比对流程
在自动化测试中,通常需要动态截图并比对,例如判断某个页面是否加载成功。
# 连接设备
device = MonkeyRunner.waitForConnection()
# 启动应用
device.startActivity(component='com.example.app/.MainActivity')
# 等待页面加载
MonkeyRunner.sleep(3)
# 截图并保存为参考图像
reference_image = device.takeSnapshot()
reference_image.writeToFile('/tmp/reference.png', 'png')
# 模拟点击按钮
device.touch(500, 800, 'DOWN_AND_UP')
# 等待界面变化
MonkeyRunner.sleep(2)
# 获取新截图
new_image = device.takeSnapshot()
# 比对
if reference_image.sameAs(new_image, 0.95):
print("界面未发生变化,可能操作失败。")
else:
print("界面状态变化成功。")
代码逻辑分析:
- 首先获取页面加载后的参考图像。
- 然后模拟操作后再次截图,并与参考图像比对。
- 如果图像相似度低于阈值,说明界面状态发生变化,操作成功。
流程总结:
- 获取参考图像。
- 执行操作。
- 获取新图像。
- 比对判断状态变化。
3.3 图像识别在测试场景中的应用
图像识别技术在自动化测试中具有广泛的应用价值。它可以帮助测试人员快速验证UI状态、检测异常界面、判断操作是否成功等。
3.3.1 判断特定界面是否加载成功
在自动化测试中,判断应用是否成功跳转到指定界面是一个常见需求。可以通过截图比对来实现:
# 获取当前界面截图
current_image = device.takeSnapshot()
# 读取预存的正确界面截图
expected_image = MonkeyRunner.loadImageFromFile('/tmp/login_success.png')
# 比对
if current_image.sameAs(expected_image, 0.95):
print("登录成功界面已加载。")
else:
print("登录界面加载失败或出现异常。")
代码逻辑分析:
-
loadImageFromFile():从本地加载预存的标准图像。 - 通过比对当前截图与标准图像判断界面状态。
应用场景:
- 登录成功判断。
- 页面跳转验证。
- 引导页展示检测。
3.3.2 验证UI元素状态变化
在一些交互测试中,我们需要验证某个UI元素的状态是否发生变化,例如按钮是否被点击、图标是否被点亮等。
# 初始截图
before_click = device.takeSnapshot()
# 点击按钮
device.touch(300, 600, 'DOWN_AND_UP')
# 等待状态变化
MonkeyRunner.sleep(1)
# 点击后截图
after_click = device.takeSnapshot()
# 比对
if before_click.sameAs(after_click, 0.95):
print("按钮状态未变化,点击可能无效。")
else:
print("按钮状态已变化,操作成功。")
代码逻辑分析:
- 通过比对点击前后的图像判断UI元素状态是否发生变化。
- 可用于验证按钮、开关、图标等交互控件。
应用场景:
- 开关状态验证。
- 图标点亮/熄灭检测。
- 按钮点击反馈验证。
3.3.3 自动化测试中的图像识别异常处理
在图像识别过程中,可能会遇到图像模糊、分辨率不一致、设备未连接等问题。合理的异常处理机制可以提升脚本的健壮性。
try:
# 尝试获取设备连接
device = MonkeyRunner.waitForConnection(timeout=10)
if device is None:
raise Exception("设备连接超时")
# 获取截图
image = device.takeSnapshot()
if image is None:
raise Exception("截图失败")
# 比对逻辑
...
except Exception as e:
print(f"发生异常:{str(e)}")
代码逻辑分析:
- 使用
try-except结构捕获异常。 - 对设备连接、截图失败等常见问题进行处理。
- 提升脚本稳定性。
异常处理建议:
- 检查设备连接状态。
- 设置截图超时时间。
- 对比对失败进行日志记录。
表格:MonkeyImage常用方法汇总
| 方法名 | 功能描述 | 参数说明 |
|---|---|---|
takeSnapshot() | 获取当前设备屏幕截图 | 无 |
getSubImage() | 裁剪图像指定区域 | (x, y, width, height) |
resize() | 缩放图像 | (width, height), quality |
getRawPixel() | 获取指定像素点的颜色值 | x, y |
sameAs() | 比较两张图像是否一致 | otherImage, percent |
writeToFile() | 将图像保存到本地文件 | file, format |
Mermaid流程图:图像识别测试流程图
graph TD
A[启动应用] --> B[获取参考图像]
B --> C[执行操作]
C --> D[获取新图像]
D --> E{图像比对}
E -- 相似度高 --> F[界面未变化]
E -- 相似度低 --> G[界面变化成功]
通过本章的深入讲解,我们可以看到MonkeyImage类在自动化测试中的强大图像处理能力。从基础的截图、裁剪、像素访问,到图像比对和实际测试场景的应用,MonkeyImage为UI验证提供了可靠的技术支持。在下一章中,我们将进一步探讨MonkeyRunner的API调用与事件模拟实战技巧。
4. MonkeyRunner API调用与事件模拟实战
MonkeyRunner作为Android平台上的自动化测试工具,其核心优势在于提供了丰富且灵活的API接口,支持对设备行为、图像识别、事件模拟等多维度的自动化操作。本章将围绕MonkeyRunner API的调用方式、用户行为模拟、脚本编写规范以及实际案例进行系统讲解,帮助读者掌握如何通过MonkeyRunner构建高效、稳定的自动化测试流程。
4.1 MonkeyRunner核心API解析
MonkeyRunner的API体系结构主要由三个核心类组成: MonkeyRunner 、 MonkeyDevice 和 MonkeyImage 。这些类封装了与设备交互、图像处理、事件模拟等关键功能,是编写自动化脚本的基础。
4.1.1 MonkeyRunner类的主要方法
MonkeyRunner 类是脚本的入口类,提供了启动设备连接、等待设备、脚本暂停等功能。其常用方法如下:
| 方法名 | 描述 |
|---|---|
MonkeyRunner.waitForConnection() | 等待设备连接 |
MonkeyRunner.sleep(seconds) | 暂停脚本执行指定时间(秒) |
MonkeyRunner.alert(message, title, okTitle) | 弹出提示对话框 |
MonkeyRunner.loadImageFromFile(path) | 从文件加载图像 |
示例代码:
from com.android.monkeyrunner import MonkeyRunner
# 等待设备连接
device = MonkeyRunner.waitForConnection()
# 暂停5秒
MonkeyRunner.sleep(5)
# 弹出提示框
MonkeyRunner.alert("测试开始", "提示", "继续")
代码分析:
-
waitForConnection():用于等待Android设备通过USB连接到PC,成功连接后返回MonkeyDevice对象。 -
sleep():用于控制脚本执行节奏,避免操作过于密集导致设备响应延迟。 -
alert():调试时用于提示信息,增强脚本交互性。
4.1.2 MonkeyDevice与MonkeyImage的API调用方式
MonkeyDevice 主要用于与设备交互,如启动应用、发送事件等;而 MonkeyImage 则用于图像处理,如截图、像素访问等。
示例:启动应用并截图
# 启动指定应用
device.startActivity(component="com.example.app/.MainActivity")
# 等待3秒确保界面加载完成
MonkeyRunner.sleep(3)
# 截图并保存
result = device.takeSnapshot()
result.writeToFile('/tmp/screenshot.png', 'png')
参数说明:
-
startActivity():启动目标Activity,参数格式为包名/全类名。 -
takeSnapshot():获取当前设备屏幕截图,返回MonkeyImage对象。 -
writeToFile():将图像保存为指定格式的文件。
4.1.3 自定义函数与模块化封装
为了提升代码的可读性和可维护性,建议将常用操作封装成函数或模块。
def launch_app(device, package, activity):
"""
启动指定应用
:param device: MonkeyDevice对象
:param package: 应用包名
:param activity: Activity类名
"""
device.startActivity(component=f"{package}/{activity}")
MonkeyRunner.sleep(2)
使用方式:
launch_app(device, "com.example.app", ".MainActivity")
优点:
- 提高代码复用率
- 增强脚本结构清晰度
- 方便后期维护和扩展
4.2 用户行为模拟与事件组合
MonkeyRunner支持模拟用户行为,如点击、滑动、输入等,并能模拟系统事件,如设备旋转、来电、断网等。
4.2.1 构建复杂的用户操作序列
自动化测试中,通常需要模拟一系列操作来覆盖完整的用户行为路径。例如登录、提交表单、点击菜单等。
# 点击登录按钮坐标
device.touch(500, 800, 'DOWN_AND_UP')
# 输入用户名
device.type("testuser")
# 点击密码框并输入
device.touch(500, 900, 'DOWN_AND_UP')
device.type("password123")
逻辑分析:
-
touch(x, y, type):在指定坐标执行点击操作,'DOWN_AND_UP'表示按下并释放。 -
type(text):模拟键盘输入,适用于输入框操作。
4.2.2 模拟设备旋转、来电、断网等系统事件
MonkeyRunner还支持模拟一些系统级事件,有助于测试应用在特定系统状态下的表现。
# 模拟设备旋转为横屏
device.press("KEYCODE_APP_SWITCH", "DOWN_AND_UP")
MonkeyRunner.sleep(1)
device.press("KEYCODE_APP_SWITCH", "DOWN_AND_UP")
# 模拟来电
device.broadcastIntent(action="android.intent.action.PHONE_STATE",
data="tel:1234567890",
category="android.intent.category.DEFAULT")
参数说明:
-
press(key, type):模拟按键按下事件,KEYCODE_APP_SWITCH是Android中的切换任务键。 -
broadcastIntent():发送广播意图,用于模拟系统事件。
4.2.3 实现脚本的逻辑判断与条件执行
在自动化测试中,常常需要根据条件判断是否执行某段代码。虽然MonkeyRunner本身不支持高级逻辑判断,但可以结合Python进行控制。
if is_login_successful(image):
print("登录成功")
else:
print("登录失败")
函数实现示例:
def is_login_successful(snapshot):
expected = MonkeyRunner.loadImageFromFile("/tmp/login_success.png")
return snapshot.sameAs(expected, 0.9)
流程图:
graph TD
A[开始测试] --> B{是否登录成功?}
B -- 是 --> C[输出“登录成功”]
B -- 否 --> D[输出“登录失败”]
4.3 自动化测试脚本编写规范
良好的脚本编写规范可以提升测试效率、降低维护成本,是构建稳定自动化测试体系的重要基础。
4.3.1 脚本结构设计与模块划分
建议采用模块化结构组织脚本,例如:
test_login.py
utils/
__init__.py
device_utils.py
image_utils.py
device_utils.py 示例:
def connect_device():
return MonkeyRunner.waitForConnection()
image_utils.py 示例:
def compare_image(snapshot, expected_path, threshold=0.9):
expected = MonkeyRunner.loadImageFromFile(expected_path)
return snapshot.sameAs(expected, threshold)
4.3.2 日志记录与调试技巧
MonkeyRunner脚本本身不支持日志输出,但可以通过Python的 print() 或日志模块进行记录。
import logging
logging.basicConfig(level=logging.INFO)
def log_info(message):
logging.info(f"[TEST] {message}")
使用方式:
log_info("开始执行登录测试")
4.3.3 提高脚本的可维护性与可扩展性
- 使用常量定义关键参数(如坐标、包名等)
- 将重复操作封装为函数
- 使用配置文件管理设备信息、测试数据等
# config.py
APP_PACKAGE = "com.example.app"
APP_ACTIVITY = ".MainActivity"
LOGIN_SUCCESS_IMG = "/tmp/login_success.png"
4.4 典型案例分析与实践
通过实际案例可以更直观地理解MonkeyRunner在自动化测试中的应用。以下将通过登录流程、表单提交、多场景切换三个典型场景进行演示。
4.4.1 登录流程自动化测试
测试目标:
- 启动应用并进入登录界面
- 输入用户名和密码
- 点击登录按钮
- 验证是否跳转至首页
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
# 启动应用
device = MonkeyRunner.waitForConnection()
device.startActivity(component="com.example.app/.LoginActivity")
MonkeyRunner.sleep(3)
# 输入用户名
device.touch(500, 800, 'DOWN_AND_UP')
device.type("testuser")
# 输入密码
device.touch(500, 900, 'DOWN_AND_UP')
device.type("password123")
# 点击登录
device.touch(500, 1000, 'DOWN_AND_UP')
# 截图验证是否进入首页
snapshot = device.takeSnapshot()
expected = MonkeyRunner.loadImageFromFile("/tmp/home_page.png")
assert snapshot.sameAs(expected, 0.9), "登录失败"
4.4.2 表单提交与错误提示验证
测试目标:
- 提交空表单
- 验证是否弹出错误提示
- 输入合法数据后再次提交
# 提交空表单
device.touch(500, 1100, 'DOWN_AND_UP')
# 截图判断是否显示错误提示
snapshot = device.takeSnapshot()
error_img = MonkeyRunner.loadImageFromFile("/tmp/error_prompt.png")
assert snapshot.sameAs(error_img, 0.9), "错误提示未显示"
# 输入数据并重新提交
device.touch(500, 900, 'DOWN_AND_UP')
device.type("valid_data")
device.touch(500, 1100, 'DOWN_AND_UP')
4.4.3 多场景切换与状态恢复测试
测试目标:
- 切换应用前后台
- 模拟来电中断
- 回到应用验证状态是否保持
# 启动应用
device.startActivity(component="com.example.app/.MainActivity")
MonkeyRunner.sleep(2)
# 模拟来电
device.broadcastIntent(action="android.intent.action.PHONE_STATE",
data="tel:1234567890",
category="android.intent.category.DEFAULT")
MonkeyRunner.sleep(3)
# 返回应用
device.press("KEYCODE_APP_SWITCH", "DOWN_AND_UP")
MonkeyRunner.sleep(1)
device.touch(500, 800, 'DOWN_AND_UP')
# 截图验证界面状态
snapshot = device.takeSnapshot()
expected = MonkeyRunner.loadImageFromFile("/tmp/resumed_state.png")
assert snapshot.sameAs(expected, 0.9), "应用状态未正确恢复"
流程图:
graph TD
A[启动应用] --> B[模拟来电]
B --> C[返回应用]
C --> D[验证状态是否恢复]
通过本章的学习,读者应掌握MonkeyRunner的核心API调用方式、用户行为模拟方法、脚本编写规范以及典型测试案例的实现。这些内容将为后续的脚本录制、测试整合打下坚实基础。
5. MonkeyRunner脚本录制与测试流程整合
MonkeyRunner 提供了脚本录制工具,可以将用户的实际操作记录下来,自动生成可执行的 Python 脚本。这一功能极大地提升了测试脚本的编写效率,尤其适用于界面复杂、操作路径多样的测试场景。本章将从脚本录制工具的使用开始,逐步讲解脚本的优化、执行控制,最后介绍如何将其与主流测试框架及持续集成系统整合,构建完整的自动化测试流程。
5.1 脚本录制工具的使用
MonkeyRunner 提供了两个官方录制工具: monkey_recorder.py 和 monkey_playback.py ,分别用于录制和回放脚本。
5.1.1 monkey_recorder.py的使用方法
monkey_recorder.py 是一个用于记录用户操作并生成 Python 脚本的工具。它会监听设备上的点击、滑动、输入等事件,并将这些操作转换为 MonkeyRunner 的 API 调用。
使用步骤如下:
# 进入 Android SDK 的 tools 目录
cd /path/to/android-sdk/tools
# 启动录制脚本
python monkey_recorder.py
启动后,工具会自动连接设备并开始监听操作。用户可以在设备上进行点击、滑动、输入等操作,这些操作将被记录并输出到控制台。
注意:
monkey_recorder.py默认将操作输出到终端,如果需要保存为脚本文件,可以使用重定向:
python monkey_recorder.py > recorded_script.py
5.1.2 用户操作的录制与脚本生成
在设备上执行一系列操作后, monkey_recorder.py 会生成类似以下格式的脚本:
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
device = MonkeyRunner.waitForConnection()
device.touch(100, 200, 'DOWN_AND_UP')
MonkeyRunner.sleep(1)
device.type('hello world')
MonkeyRunner.sleep(2)
device.press('KEYCODE_MENU', 'DOWN_AND_UP')
该脚本可以直接保存为 .py 文件,并通过以下方式执行:
python recorded_script.py
5.1.3 录制脚本的优化与调整
录制生成的脚本通常需要进行优化,以提高可读性和健壮性。例如:
- 添加注释 :为每个操作添加说明,便于后续维护。
- 封装重复操作 :将常用操作封装为函数。
- 添加异常处理 :防止设备连接失败或操作超时导致脚本中断。
优化示例:
def click_login_button(device):
# 点击登录按钮
device.touch(200, 300, 'DOWN_AND_UP')
MonkeyRunner.sleep(1)
def input_username(device, username):
# 输入用户名
device.type(username)
MonkeyRunner.sleep(1)
# 主流程
device = MonkeyRunner.waitForConnection()
if device is None:
print("设备连接失败")
sys.exit(1)
input_username(device, 'test_user')
click_login_button(device)
5.2 脚本回放与执行控制
录制脚本完成后,可以通过 monkey_playback.py 工具进行回放,并结合异常处理机制提升脚本的稳定性。
5.2.1 monkey_playback.py的功能与使用
monkey_playback.py 是一个用于执行录制脚本的工具,支持对录制脚本进行回放:
python monkey_playback.py recorded_script.py
该工具会按录制顺序依次执行脚本中的每一条命令。
5.2.2 脚本回放中的异常处理机制
为了防止脚本在执行过程中因设备断开、界面加载延迟等原因中断,可以添加异常处理逻辑:
try:
device = MonkeyRunner.waitForConnection(5)
if device is None:
raise Exception("设备连接超时")
# 执行脚本逻辑
device.touch(100, 200, 'DOWN_AND_UP')
except Exception as e:
print(f"执行异常: {e}")
# 可在此添加日志记录或截图操作
5.2.3 控制执行节奏与断点调试
通过 MonkeyRunner.sleep() 可以控制脚本执行节奏,避免因设备响应慢导致的失败:
MonkeyRunner.sleep(2) # 等待2秒
还可以在关键操作后添加截图功能,用于调试或结果验证:
result = device.takeSnapshot()
result.writeToFile('login_page.png', 'png')
5.3 MonkeyRunner与测试框架的集成
将 MonkeyRunner 脚本与测试框架集成,可以实现测试用例管理、结果分析、报告生成等功能。
5.3.1 结合unittest框架构建测试用例
Python 的 unittest 框架可用于构建结构化的测试用例。以下是将 MonkeyRunner 脚本封装为 unittest 测试用例的示例:
import unittest
from com.android.monkeyrunner import MonkeyRunner
class TestLogin(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.device = MonkeyRunner.waitForConnection()
def test_login(self):
self.device.touch(100, 200, 'DOWN_AND_UP')
MonkeyRunner.sleep(1)
self.device.type('test_user')
# 添加断言逻辑
if __name__ == '__main__':
unittest.main()
5.3.2 测试报告生成与结果分析
可以通过 HTMLTestRunner 或 pytest 插件生成测试报告,便于分析执行结果。例如:
pip install html-testRunner
然后在脚本中导入并使用:
import HTMLTestRunner
runner = HTMLTestRunner.HTMLTestRunner(output='test_reports')
runner.run(unittest.TestLoader().loadTestsFromTestCase(TestLogin))
5.3.3 实现测试用例的批量执行与管理
可以将多个测试用例组织为测试套件(TestSuite),并批量执行:
suite = unittest.TestSuite()
suite.addTest(TestLogin('test_login'))
suite.addTest(TestRegister('test_register'))
runner = unittest.TextTestRunner()
runner.run(suite)
5.4 自动化测试流程整合与持续集成
将 MonkeyRunner 集成到持续集成系统中,可以实现测试流程的自动化运行与结果反馈。
5.4.1 Jenkins与MonkeyRunner的集成方案
Jenkins 是一个流行的持续集成工具。可以创建一个 Jenkins Job,执行以下步骤:
- 拉取测试脚本仓库
- 安装 Python 依赖
- 执行 MonkeyRunner 测试脚本
- 生成测试报告
- 发送测试结果邮件通知
Jenkins Pipeline 示例:
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git branch: 'main', url: 'https://your-repo-url.git'
}
}
stage('Run Tests') {
steps {
sh 'cd monkeyrunner_tests && python -m unittest discover'
}
}
stage('Generate Report') {
steps {
sh 'cd monkeyrunner_tests && python generate_report.py'
}
}
}
}
5.4.2 定时任务与远程执行配置
可以通过 Jenkins 的定时任务功能设置每天固定时间执行测试任务:
triggers {
cron('0 8 * * *') // 每天早上8点执行
}
同时,Jenkins 支持远程触发构建,可通过 HTTP 请求远程启动测试流程:
curl -X POST --user user:token http://jenkins-url/job/monkeyrunner-job/build
5.4.3 构建完整的自动化测试流水线
一个完整的自动化测试流水线应包括:
- 代码提交触发测试
- 自动化测试脚本执行
- 测试结果收集与分析
- 报告生成与通知
- 失败自动重试机制
通过将 MonkeyRunner 集成到 Jenkins 等 CI/CD 工具中,可以实现从开发到测试再到部署的全链路自动化流程,显著提升测试效率与质量保障能力。
简介:MonkeyRunner是Android SDK中的自动化测试工具,支持通过Python脚本控制设备或模拟器,执行如点击、滑动、文本输入、截图等操作。适用于应用自动化测试及批量任务处理。本资源包包含多个示例脚本,如录制回放、帮助文档生成、设备控制等,帮助开发者快速掌握MonkeyRunner的使用方法与核心API,提升测试效率与自动化能力。
更多推荐
所有评论(0)