1. 项目背景与痛点分析
在移动应用测试领域,跨设备兼容性一直是困扰测试团队的难题。以我们团队为例,使用Airtest纯视觉方案进行自动化测试时,经常遇到这样的场景:在华为P40上运行良好的测试脚本,到了小米12上就频频失败,原因仅仅是同一个按钮在不同机型上的位置偏移了几个像素。这种问题在传统解决方案中,需要为每个机型单独维护图像模板库,工作量呈几何级数增长。
更棘手的是,随着Android生态的碎片化加剧,不同厂商对系统UI的定制越来越深。比如输入法小键盘的收起按钮,华为放在右下角,小米可能放在左上角,OPPO又可能使用完全不同的图标样式。传统基于图像识别的方案在这种场景下捉襟见肘,测试脚本的维护成本居高不下。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术方案选型
2.1 传统方案的局限性
传统Airtest纯视觉方案的工作流程大致如下:
- 录制阶段:在参考设备上截取目标控件的图像作为模板
- 执行阶段:在当前设备屏幕上搜索匹配的模板图像
- 操作阶段:对匹配区域进行点击、滑动等操作
这种方案存在三个致命缺陷:
- 图像模板需要覆盖所有可能的设备型号和分辨率
- 对UI样式变化极度敏感,按钮颜色变化都可能导致匹配失败
- 无法处理动态元素(如浮动按钮)
2.2 大模型带来的新思路
Open-AutoGLM这类基于大模型的APP Agent展示了全新的可能性。其核心优势在于:
- 视觉理解能力:能真正"看懂"屏幕内容,而非简单像素匹配
- 语义理解能力:可以接受自然语言指令
- 决策能力:能自主规划操作路径
但完整部署这类AI Agent对中小企业来说存在现实障碍:
- 硬件成本:本地运行大模型需要高端GPU,单卡成本超2万元
- 技术门槛:涉及模型微调、服务部署等复杂环节
- 维护成本:需要持续优化prompt和适配新机型
2.3 折中方案设计
我们的创新点在于:只抽取AI Agent最核心的视觉定位能力,与现有Airtest框架结合。具体架构如下:
code复制[手机屏幕] → [Airtest截图] → [大模型视觉识别] → [相对坐标] → [Airtest绝对坐标转换] → [执行操作]
这种混合架构既保留了Airtest轻量易用的特点,又获得了大模型的智能识别能力,实现了1+1>2的效果。
3. 关键技术实现细节
3.1 环境配置与依赖管理
项目采用Python 3.8+环境,主要依赖包包括:
- airtest:1.2.6版本,提供设备连接和基础操作能力
- zhipuai:最新版,智谱AI官方SDK
- json-repair:用于处理大模型返回的非标准JSON
建议使用virtualenv创建隔离环境:
bash复制python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
pip install airtest zhipuai json-repair
3.2 核心模块实现
3.2.1 设备管理模块
python复制def init_device(device_serial):
"""初始化Airtest设备连接"""
from airtest.core.api import connect_device
dev = connect_device(f"Android:///{device_serial}?cap_method=javacap")
if not dev:
raise RuntimeError("设备连接失败")
return dev
关键参数说明:
cap_method=javacap:使用Java层截图,比minicap更稳定touch_method=adb:确保点击坐标精确
3.2.2 大模型交互模块
python复制class GLMClient:
def __init__(self, api_key):
self.client = ZhipuAI(api_key=api_key)
self.model = "glm-4.6v-flash"
def analyze_screen(self, image_path, prompt):
"""发送截图和指令给大模型"""
with open(image_path, "rb") as f:
img_base64 = base64.b64encode(f.read()).decode()
response = self.client.chat.completions.create(
model=self.model,
messages=[{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": img_base64}}
]
}],
temperature=0.1
)
return self._parse_response(response.choices[0].message.content)
注意事项:
- 图像需要转换为base64编码
- temperature参数设为0.1降低输出随机性
- 需要处理可能返回的非标准JSON
3.2.3 坐标转换模块
python复制def convert_coordinates(rel_x, rel_y, device):
"""将相对坐标(0-1000)转换为设备绝对坐标"""
w, h = device.get_current_resolution()
abs_x = int(rel_x / 1000 * w)
abs_y = int(rel_y / 1000 * h)
return (abs_x, abs_y)
处理不同分辨率设备的适配问题,确保点击位置准确。
3.3 完整工作流程
- 设备连接与初始化
- 触发目标界面(如打开输入法)
- 截取当前屏幕
- 发送截图和指令给大模型
- 解析返回的坐标信息
- 坐标转换并执行操作
- 验证操作结果
4. 实战案例:跨设备输入法测试
4.1 测试场景构建
我们设计了一个典型测试场景:在不同品牌设备上自动收起输入法键盘。传统方案需要在每台设备上:
- 手动截取收起按钮的模板图片
- 调整匹配阈值参数
- 编写异常处理逻辑
而新方案只需要一条统一的指令:"请找到并点击收起键盘的按钮"
4.2 效果对比
在以下设备上测试结果:
| 设备型号 | 传统方案适配时间 | 新方案适配时间 | 成功率 |
|---|---|---|---|
| 华为P40 | 30分钟 | 0分钟 | 98% |
| 小米12 | 25分钟 | 0分钟 | 97% |
| OPPO Reno6 | 35分钟 | 0分钟 | 96% |
| vivo X80 | 28分钟 | 0分钟 | 95% |
4.3 性能数据
平均单次操作耗时:
- 截图:200ms
- 大模型推理:800ms
- 坐标转换:50ms
- 点击操作:100ms
总耗时约1.2秒,相比人工维护多套模板的方案,效率提升显著。
5. 优化方向与实践建议
5.1 成本控制策略
大模型API调用成本是主要考量,推荐以下优化手段:
- 结果缓存:对相同界面元素建立坐标缓存
python复制from functools import lru_cache
@lru_cache(maxsize=100)
def get_element_position(image_hash, prompt):
# 缓存逻辑
- 图像压缩:在不影响识别的前提下减小图像尺寸
python复制def compress_image(img_path, quality=70):
from PIL import Image
img = Image.open(img_path)
img.save(img_path, quality=quality)
5.2 稳定性提升方案
- 重试机制:对大模型调用失败的情况自动重试
python复制retry_count = 0
max_retries = 3
while retry_count < max_retries:
try:
response = glm_client.analyze_screen(...)
break
except Exception as e:
retry_count += 1
- 备选策略:当大模型不可用时回退到传统图像匹配
python复制def smart_click(prompt):
try:
# 尝试AI方案
ai_click(prompt)
except Exception:
# 回退到传统方案
traditional_image_click()
5.3 扩展应用场景
- 动态弹窗处理:自动识别和关闭各种广告弹窗
- 异常检测:识别界面异常状态(如加载失败)
- 多语言支持:通过大模型实现多语言文本识别
6. 经验总结与避坑指南
在实际落地过程中,我们积累了一些宝贵经验:
- 图像质量至关重要:
- 避免截图时屏幕亮度太低
- 确保截图不包含手指遮挡等干扰
- 推荐使用ADB截图而非视频流截图
- prompt工程技巧:
- 明确指定需要操作的元素类型
- 示例:"请找到界面右下角的蓝色圆形返回按钮"
- 避免模糊的描述:"找返回按钮"
- 坐标处理注意事项:
- 大模型返回的坐标可能有轻微偏差
- 建议在目标区域中心点附近随机偏移
python复制# 在目标坐标附近增加随机偏移
x += random.randint(-5, 5)
y += random.randint(-5, 5)
- 设备兼容性测试:
- 不同厂商的ADB实现有差异
- 需要测试各种点击方式(adb、minitouch等)
- 全面覆盖不同Android版本
这套方案已经在我们的测试体系中运行3个月,累计执行超过1万次自动化测试任务,跨设备兼容性问题减少约80%,维护成本降低60%。对于中小团队来说,这种轻量级AI赋能方案确实能在有限投入下获得最大收益。
