- 测试
- 质量保障
- 计算机视觉
【免费下载链接】Airtest
UI Automation Framework for Games and Apps
本文围绕 Airtest 中 airtest/core/android/constant.py 这一核心常量模块展开,系统讲解 Airtest Android 自动化框架如何通过一组集中定义的常量与策略枚举,完成 adb 可执行文件定位、SDK 版本判断、屏幕采集/触控/输入法/方向监听方案的选择。读完本文,你将掌握这些常量在 Android 设备类、ADB 封装、方向监听器 中的真实调用关系,并能在接入 Android 设备时准确理解或调整默认策略。
模块定位:Android 自动化策略的"总调度表"
constant模块(对应的 Sphinx 文档页为 docs/all_module/airtest.core.android.constant.rst,通过automodule指令自动收录全部成员)是 Airtest Android 子系统的常量集中地。它表面上只是一组路径、数值与字符串常量,但实际上承担着三个关键职责:
- 资源定位:给出内置 adb 可执行文件、minicap/minitouch 原生库、Yosemite APK、rotationwatcher 工具包在包内的静态路径;
- 版本门槛:定义 Android 7 与 Android 10 两个 SDK 版本阈值,作为底层命令兼容与触控策略切换的依据;
- 策略枚举:通过
CAP_METHOD、TOUCH_METHOD、IME_METHOD、ORI_METHOD四个类,把可插拔的采集、触控、输入法、方向方案统一编码为字符串常量,供Android设备类构造与代理组件消费。
从源码结构看,airtest/core/android下几乎所有核心模块(android.py、adb.py、rotation.py、ime.py、yosemite.py、cap_methods/*、touch_methods/*)都直接或间接引用了本模块的常量,因此理解它是理解 Airtest Android 架构的一把钥匙。
一、内置二进制与 APK 的静态资源路径
constant.py开头通过THISPATH定位模块所在目录,进而拼接出STATICPATH(即 airtest/core/android/static 目录)下的各类资源:
THISPATH = decode_path(os.path.dirname(os.path.realpath(__file__))) STATICPATH = os.path.join(THISPATH, "static") STFLIB = os.path.join(STATICPATH, "stf_libs") ROTATIONWATCHER_APK = os.path.join(STATICPATH, "apks", "RotationWatcher.apk") ROTATIONWATCHER_PACKAGE = "jp.co.cyberagent.stf.rotationwatcher" YOSEMITE_APK = os.path.join(STATICPATH, "apks", "Yosemite.apk") YOSEMITE_PACKAGE = 'com.netease.nie.yosemite' YOSEMITE_IME_SERVICE = 'com.netease.nie.yosemite/.ime.ImeService' MAXTOUCH_JAR = os.path.join(STATICPATH, "apks", "maxpresent.jar") ROTATIONWATCHER_JAR = os.path.join(STATICPATH, "apks", "rotationwatcher.jar")各常量的含义与消费方如下:
| 常量 | 指向的资源 | 主要消费方 |
|---|---|---|
STFLIB | static/stf_libs目录,内含各 ABI 的 minicap/minitouch 二进制与minicap.so共享库 | minicap.py(拼接minicap-shared/aosp/libs/android-{api}/{abi}/minicap.so)、minitouch.py |
ROTATIONWATCHER_APK/ROTATIONWATCHER_PACKAGE | RotationWatcher.apk 及包名jp.co.cyberagent.stf.rotationwatcher | rotation.py 的安装与启动逻辑 |
ROTATIONWATCHER_JAR | rotationwatcher.jar,推送到设备/data/local/tmp后通过 nbsp 读取旋转事件 | rotation.py |
YOSEMITE_APK/YOSEMITE_PACKAGE | Yosemite.apk 及包名com.netease.nie.yosemite,NetEase 自研的辅助能力扩展包 | yosemite.py、yosemite_ext.py |
YOSEMITE_IME_SERVICE | Yosemite 输入法服务组件com.netease.nie.yosemite/.ime.ImeService | ime.py 中启用/切换输入法 |
MAXTOUCH_JAR | maxpresent.jar,Maxtouch 触控方案的服务端程序 | maxtouch.py,推送到设备/data/local/tmp后启动 |
这些资源在仓库中均可找到实体文件,例如 static/apks/Yosemite.apk、static/apks/maxpresent.jar、static/apks/rotationwatcher.jar,以及static/stf_libs下按 ABI 目录组织的原生二进制。
二、DEFAULT_ADB_PATH:内置 adb 的平台分发表
DEFAULT_ADB_PATH是一个以"系统名"或"系统名-机器架构"为键的字典:
DEFAULT_ADB_PATH = { "Windows": os.path.join(STATICPATH, "adb", "windows", "adb.exe"), "Darwin": os.path.join(STATICPATH, "adb", "mac", "adb"), "Linux": os.path.join(STATICPATH, "adb", "linux", "adb"), "Linux-x86_64": os.path.join(STATICPATH, "adb", "linux", "adb"), "Linux-armv7l": os.path.join(STATICPATH, "adb", "linux_arm", "adb"), }对应仓库中的实际文件为 static/adb/windows/adb.exe、static/adb/mac/adb、static/adb/linux/adb 与 static/adb/linux_arm/adb。
它在 adb.py 的builtin_adb_path()中被解析:
system = platform.system() machine = platform.machine() adb_path = DEFAULT_ADB_PATH.get('{}-{}'.format(system, machine)) if not adb_path: adb_path = DEFAULT_ADB_PATH.get(system) if not adb_path: raise RuntimeError("No adb executable supports this platform({}-{}).".format(system, machine)) if system != "Windows": make_file_executable(adb_path) # 非 Windows 平台补可执行权限 return adb_path解析策略是"先精确后兜底":优先匹配Linux-x86_64、Linux-armv7l这类带机器架构的键,找不到再回退到纯系统名(如 Windows 的 x86/x64 均使用同一 adb.exe),仍找不到则抛出RuntimeError。这也解释了为什么常量表同时存在"Linux"与"Linux-x86_64"两个键——前者用于非 x86_64 的通用 Linux 兜底,后者是主流桌面 Linux 的精确匹配。另外,adb.py中实际是通过ADB.builtin_adb_path()取得该路径,若本机另有 adb,也可通过Android(..., adb_path=...)显式指定。
三、DEFAULT_ADB_SERVER 与 DEBUG
DEFAULT_ADB_SERVER = ('127.0.0.1', 5037) DEBUG = TrueDEFAULT_ADB_SERVER定义了 adb server 的默认监听地址与端口(127.0.0.1, 5037)。在 adb.py 的_set_cmd_options()中,未显式传入server_addr时即使用该元组作为 host 与 port,并且在 host 不是localhost/127.0.0.1时追加-P端口参数以连接远程 adb server。iOS 侧 airtest/core/ios/constant.py 也定义了同名DEBUG常量,可见这是框架级的调试开关约定。DEBUG = True作为全局调试标志,供日志输出等环节使用;需要说明的是,airtest/core/settings.py中的Settings还提供了DEBUG等运行时设置项,可结合使用。
四、SDK 版本阈值:Android 7 与 Android 10 两条分界线
SDK_VERISON_ANDROID7 = 24 # Android 7.0 的 SDK 版本 SDK_VERISON_ANDROID10 = 29 # Android 10 的 SDK 版本注意常量名中VERISON为项目沿用的拼写(保持原样)。这两个阈值在框架中承担不同职责:
1. Android 7(SDK 24)—— adb shell 命令兼容分界线
在 adb.py 的shell()中,当sdk_version < SDK_VERISON_ANDROID7时(即 Android 6 及以下),adb shell 不会向上层传递非零退出码,因此框架会手动为命令追加; echo ---$?---,再通过正则re.match("(.*)---(\d+)---$", out, re.DOTALL)解析真实返回码并抛出AdbShellError;SDK 24 及以上则直接依赖raw_shell的异常传播。同样的阈值还出现在 adbcap.py(sdk_version <= SDK_VERISON_ANDROID7时采集截图前的方向处理)与 adb.py(高版本系统的输入事件模拟差异)中。
2. Android 10(SDK 29)—— 触控方案自动切换分界线
在 android.py 的Android.__init__中:
self.sdk_version = self.adb.sdk_version if self.sdk_version >= SDK_VERISON_ANDROID10 and self._touch_method == TOUCH_METHOD.MINITOUCH: self._touch_method = TOUCH_METHOD.MAXTOUCH即 Android 10 及以上设备若默认选择了 MINITOUCH,会因 minitouch 在新系统上的兼容问题自动切换为 MAXTOUCH。SDK 版本本身来自 adb.py 的sdk_version属性,通过getprop ro.build.version.sdk获取并缓存,这也是理解该阈值语义的关键调用链。
五、CAP_METHOD / TOUCH_METHOD / IME_METHOD / ORI_METHOD:四大策略枚举
class CAP_METHOD(object): MINICAP = "MINICAP" ADBCAP = "ADBCAP" JAVACAP = "JAVACAP" class TOUCH_METHOD(object): MINITOUCH = "MINITOUCH" MAXTOUCH = "MAXTOUCH" ADBTOUCH = "ADBTOUCH" class IME_METHOD(object): ADBIME = "ADBIME" YOSEMITEIME = "YOSEMITEIME" class ORI_METHOD(object): ADB = "ADBORI" MINICAP = "MINICAPORI"这四个类分别对应屏幕采集、触控注入、输入法、屏幕方向四个能力维度,其字符串常量与各能力实现模块的METHOD_NAME一一对应。
5.1 作为 Android 构造函数的默认参数
在 android.py 中,四个枚举直接作为Android设备类的构造参数默认值:
def __init__(self, serialno=None, host=None, cap_method=CAP_METHOD.MINICAP, touch_method=TOUCH_METHOD.MINITOUCH, ime_method=IME_METHOD.YOSEMITEIME, ori_method=ORI_METHOD.MINICAP, display_id=None, input_event=None, adb_path=None, name=None):构造时统一执行.upper()规范化,因此传入小写(如"minicap")也能正确匹配。默认组合为"MINICAP 采集 + MINITOUCH 触控 + YOSEMITEIME 输入法 + MINICAP 方向",开发者可针对低端设备、无 root 设备或特殊系统覆盖其中任意一项。
5.2 触控方案的注册表机制:TouchProxy
TouchProxy 以OrderedDict维护TOUCH_METHODS注册表,各触控实现类通过装饰器注册自己的METHOD_NAME:
ADBTOUCH→ 基于adb shell input的通用方案(兼容性最好,速度最慢);MINITOUCH→ 基于 minitouch 原生二进制的方案(速度快);MAXTOUCH→ 基于 maxpresent.jar 的方案(Android 10+ 自动切换目标)。
TouchProxy.auto_setup(adb, default_method=self._touch_method, ...)会优先尝试指定方法,失败则按注册顺序依次回退到其他可用方案,这正是"策略可插拔、失败自动降级"的设计体现。
5.3 方向监听方案的降级:RotationWatcher
rotation.py 的RotationWatcher.__init__接收ori_method=ORI_METHOD.MINICAP,其start()中:
if self.ori_method == ORI_METHOD.MINICAP: try: self.setup_server() except: LOGGING.error("RotationWatcher setup failed, use ADBORI instead.") self.ori_method = ORI_METHOD.ADB即优先使用 MINICAPORI(通过 RotationWatcher/minicap 读取旋转事件),安装或启动失败时降级为 ADBORI(通过adb.getDisplayOrientation()轮询)。方向刷新逻辑中,_refresh_by_ow()读取 nbsp 输出的角度值并除以 90 归一化为 0/1/2/3,_refresh_by_adb()则直接查询 adb 显示方向,两者由当前ori_method分支选择,进一步印证了常量与实现的双向绑定关系。
六、IP_PATTERN:IP 地址提取的公共正则
IP_PATTERN = re.compile(r'(\d+\.){3}\d+')该正则用于从文本中匹配形如xxx.xxx.xxx.xxx的 IPv4 地址,在 adb.py 与 adb.py 中通过IP_PATTERN.search(res)从 adb 输出中提取设备 IP;airtest/core/ios/constant.py 也定义了完全相同的正则供 iOS 模块使用(ios.py 从self.addr中匹配 IP),属于跨 Android/iOS 复用的工具型常量。
七、常量的实际使用场景小结
结合源码调用关系,可将本模块常量归纳为三类使用场景:
- 设备初始化:
Android(...)通过四个枚举类确定采集/触控/输入法/方向策略,并读取SDK_VERISON_ANDROID10完成 Android 10+ 的触控自动切换(见 android.py); - 命令与网络层:
ADB类使用DEFAULT_ADB_PATH定位内置 adb、用DEFAULT_ADB_SERVER设置默认 server 端口、用SDK_VERISON_ANDROID7决定 shell 返回码的兼容处理、用IP_PATTERN解析设备地址(见 adb.py); - 原生组件部署:minicap/minitouch 从
STFLIB定位 ABI 对应二进制,maxpresent.jar、rotationwatcher.jar、Yosemite.apk 分别被 Maxtouch、RotationWatcher、Yosemite 模块推送到设备端使用(见 minicap.py、maxtouch.py、rotation.py、yosemite.py)。
结语
airtest.core.android.constant虽然只是一个纯常量模块,却是 Airtest Android 自动化的"策略总表":路径常量把内置资源与平台绑定,SDK 阈值常量定义了命令兼容与触控降级的分界线,四个策略枚举类则把屏幕采集、触控注入、输入法和方向监听组织成可插拔、可自动降级的方案体系。理解这张总表,你就能在遇到设备采集失败、触控异常或方向错乱时,快速定位到对应的策略常量、代理组件与底层实现文件,从而准确调整Android(...)的初始化参数或排查原生组件部署问题。
- 测试
- 质量保障
- 计算机视觉
【免费下载链接】Airtest
UI Automation Framework for Games and Apps
相关推荐
Spree 欧盟法律合规实现指南:Omnibus 价格历史、GDPR 数据主体请求与匿名化工作流
Spree 欧盟法律合规实现指南:Omnibus 价格历史、GDPR 数据主体请求与匿名化工作流 本文基于 Spree 仓库中的实施计划 docs/plans/
测试质量保障计算机视觉lo 泛型类型操作(Type Manipulation)核心辅助函数全解析:nil 检测、指针转换与 Coalesce 家族
lo 泛型类型操作(Type Manipulation)核心辅助函数全解析:nil 检测、指针转换与 Coalesce 家族 lo 是基于 Go 1.18+ 泛
测试质量保障计算机视觉AI SDK核心模块深度解析:从文本生成到结构化输出
AI SDK核心模块深度解析:从文本生成到结构化输出 本文深入解析AI SDK的四个核心模块:generateText函数的基础文本生成原理、streamTex
人工智能AI 应用AI Agent工具调用MCP Clients
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考