Skills Plugins MCP Prompt Model 博客 我的中心

ui-test

Zhihu++ LLM 自动化 UI 测试。使用 testTag 系统精准定位 Compose 元素并交互,替代硬编码坐标的 adb tap。提供已知 tag 列表、文字内容点击、截图验证等能力。适用于:功能验证、UI 回归测试、自动化交互流程。

DeepseekModel 官方收录技能 质量 优秀 · 90 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=zly2006-zhihu-plus-plus-agents-skills-ui-test-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name ui-test description Zhihu++ LLM 自动化 UI 测试。使用 testTag 系统精准定位 Compose 元素并交互,替代硬编码坐标的 adb tap。提供已知 tag 列表、文字内容点击、截图验证等能力。适用于:功能验证、UI 回归测试、自动化交互流程。 license CC BY-NC-SA 4.0 UI 自动化测试 Skill 执行环境优先级 调用本 skill 的 UI 自动化 agent 或 subagent 时,尽量使用 gpt-5.4-mini ;复杂视觉或流程判断再使用 gpt-5.4 ,避免使用反应较慢的模型拖慢 AVD 交互。 先选择当前健康、目标 API 匹配且启动成本最低的 AVD;本地 AVD 和 $off-android-avd-ci-debug 都可以,不能仅因远端 skill 存在就强制启动 off 。 选择远端 runner 时,它只用于短生命周期 UI/AVD 验证:按需运行 status / boot-check ;真实 UI 交互要在 off 的远端 ADB 环境中执行;验证结束后运行 kill 清理。 已有本地 AVD 更快、目标 API 更匹配或远端交互入口不完整时,可以直接使用本地 AVD。 /Users/zhaoliyan/.agents/skills/off-android-avd-ci-debug/scripts/off-avd-ci-debug.sh status /Users/zhaoliyan/.agents/skills/off-android-avd-ci-debug/scripts/off-avd-ci-debug.sh boot-check /Users/zhaoliyan/.agents/skills/off-android-avd-ci-debug/scripts/off-avd-ci-debug.sh kill 失败经验 本地没有 AVD 时禁止擅自创建 “优先复用健康的本地 AVD”只适用于本机已经存在、用户允许使用的 AVD。 emulator -list-avds 为空时,不能为了完成验证自行下载 system image、创建 AVD 或改变本机 Android 设备状态;如果任务指定远程执行面,必须继续修复或等待远程执行面,远程暂时不可用时应明确报告阻塞,不能把它降级成擅自创建本地 AVD。例子:远程 runner 的 SSH 端口临时拒绝连接时,可以重试并检查远程入口,但不能据此用本机已有 system image 新建一个测试 AVD。 先判断布局占位是否破坏原有中心 在已有头部或居中布局里新增按钮时,必须先看新增控件是否占用了布局槽位并挤压原内容,而不是只评价图标本身好不好看。例子:个人页头部放在 TopAppBar title 区时,右侧 actions 会额外占据横向空间,导致头像、昵称、统计和操作按钮整体被压窄或偏离原来的视觉中心;这类问题的根因是新增按钮破坏了正常空间分配和居中关系,不是简单的“右上角是否能放搜索”。 参考图和实际截图必须逐项对齐 按参考图实现 UI 时,不能只验证自己理解的某个技术根因已经解决,还要把参考图和实际截图并排核对关键元素的位置、大小、间距和对齐关系。例子:搜索按钮即使已经不再挤压 TopAppBar 的 title 区,如果实际截图里的按钮比参考图明显更低、更靠内容中线,仍然没有照图实现;这类偏差必须继续调整,不能用“没有挤压居中”替代“位置一致”。 Feed 卡片富媒体必须先定义尺寸预算 给已有 Feed 卡片增加图片时,不能让原图宽高比直接决定卡片高度;必须先按卡片信息密度定义媒体区域的宽高预算,再用真实截图确认标题、摘要、图片和操作区仍保持主次关系。多图数量增加也不能线性撑高卡片,应切换到受限网格。例子:横向单图或多图预览的高度上限可以约为卡片可用宽度的三分之一;如果图片占据大半屏,即使裁切和加载都正常,也属于破坏 Feed 浏览效率的实现错误。 脚本入口 所有操作通过以下脚本完成(在项目根目录执行): python3 .agents/skills/ui-test/llm_test_helper.py < command > [options] LLM 操作决策树 每次需要点击元素时,按以下顺序判断如何构造命令: 需要点击某个元素 │ ├─ 该 tag 在当前界面是否唯一? │ ├─ 是(如导航 tab)→ 直接用 --tag │ │ python3 ... tap --tag nav_tab_hotlist │ │ │ └─ 否(如 feed_card_more_btn 会出现多次)→ 需要消歧 │ │ │ ├─ 知道目标卡片的标题/关键词?→ 用 --tag + --within-text │ │ python3 ... tap --tag feed_card_more_btn --within-text "ChatGPT" │ │ │ └─ 不知道具体内容,只知道位置?→ 用 --tag + --index │ python3 ... tap --tag feed_card_more_btn --index 2 │ ↑ 屏幕从上到下第3个(0-based) │ └─ 没有 testTag?→ 用 --text 按显示文字点击 python3 ... tap --text "屏蔽用户" │ ├─ 没有 text,但有 content-desc?→ 用 --desc │ python3 ... tap --desc "返回" │ └─ text/desc/tag 都没有(无标识可点击节点)?→ 用 --text "" + --index python3 ... tap --text "" --index 19 重要 : --within-text 和 --index 可以组合使用。当同一卡片内有多个相同 tag 时, --within-text 先缩小范围到目标卡片, --index 再从该范围内选第 N 个。 完整命令参考 dump — 查看当前界面关键信息元素(可点击 + 不可点击) python3 .agents/skills/ui-test/llm_test_helper.py dump 输出示例(带序号,LLM 可用序号决定 --index ): 关键信息元素(18 个,按屏幕顺序;含可点击与不可点击): [ 0] [C] 搜索 | 搜索内容 [42,86][891,212] [ 1] [C] 某条 Feed 卡片内容 [42,273][1038,775] [ 2] [C] 更多选项 [924,661][1050,787] [ 3] [N] 更多选项 [966,703][1008,745] [ 4] [C] 主页 [0,2127][200,2274] [ 5] [C] 账号 [881,2127][1080,2274] ... [C] = 可点击, [N] = 不可点击。优先点击 [C] 元素; [N] 主要用于理解上下文和做 --within-text 消歧。 label 为脚本聚合后的可读信息,不再保证固定显示 tag:/text:/desc: 前缀。 弹窗模式 :检测到弹窗时, dump 只输出弹窗内容并自动过滤无用节点(避免被背景页面干扰)。 LLM 使用规则 :执行任何 tap 前,先运行 dump 确认目标元素存在及其序号。 find — 查找元素坐标(不点击) # 列出所有 feed_card 的坐标和序号 python3 .agents/skills/ui-test/llm_test_helper.py find --tag feed_card # 找包含"AI"的卡片内的 more_btn 坐标 python3 .agents/skills/ui-test/llm_test_helper.py find --tag feed_card_more_btn --within-text "AI" --tag 支持两种 resource-id 形式: com.xxx:id/tag 和裸 tag (如 nav_tab_account )。 tap — 点击元素 场景 1:唯一元素(导航 tab、全局按钮) python3 .agents/skills/ui-test/llm_test_helper.py tap --tag nav_tab_home python3 .agents/skills/ui-test/llm_test_helper.py tap --tag nav_tab_hotlist python3 .agents/skills/ui-test/llm_test_helper.py tap --tag nav_tab_account 场景 2:按内容定位(知道目标卡片的关键词) # 点击标题含"ChatGPT"的卡片本体 python3 .agents/skills/ui-test/llm_test_helper.py tap --tag feed_card --within-text "ChatGPT" # 点击标题含"ChatGPT"的卡片的更多按钮 python3 .agents/skills/ui-test/llm_test_helper.py tap --tag feed_card_more_btn --within-text "ChatGPT" 场景 3:按位置定位(知道是第几个) # 点击屏幕上从上到下第 1 个卡片(0-based) python3 .agents/skills/ui-test/llm_test_helper.py tap --tag feed_card --index 0 # 点击第 2 个卡片的更多按钮 python3 .agents/skills/ui-test/llm_test_helper.py tap --tag feed_card_more_btn --index 1 场景 4:组合使用(最精确,内容 + 位置双重限定) # 如果某个话题下有多张卡片都含"AI",指定取其中第 2 个的更多按钮 python3 .agents/skills/ui-test/llm_test_helper.py tap --tag feed_card_more_btn --within-text "AI" --index 1 场景 5:按显示文字点击(无 testTag 的动态元素) python3 .agents/skills/ui-test/llm_test_helper.py tap --text "屏蔽用户" python3 .agents/skills/ui-test/llm_test_helper.py tap --text "取消" python3 .agents/skills/ui-test/llm_test_helper.py tap --text "登录" 场景 6:按 contentDescription 点击(无文本但有无障碍描述) python3 .agents/skills/ui-test/llm_test_helper.py tap --desc "返回" 注意:若 --desc 匹配多个节点,脚本当前不会对 desc 提供 --index 消歧。 这种情况下请优先改用 --tag ;如果没有可用 tag,请先 dump 后用 --text "" --index N 。 场景 7:点击无标识可点击节点(text/desc/tag 全为空) # 1) 先 dump,确认目标在当前页面中的相对位置 python3 .agents/skills/ui-test/llm_test_helper.py dump # 2) 再用空文本 + index 点击(index 基于当前页面 text="" 节点顺序) python3 .agents/skills/ui-test/llm_test_helper.py tap --text "" --index 19 适用场景:颜色面板色块、部分开关、部分“更多”按钮容器。 screenshot — 截图 python3 .agents/skills/ui-test/llm_test_helper.py screenshot /tmp/result.png 截图后必须用 view 工具查看,不要在同一 response 中同时发出截图和 view 命令(截图需要时间)。 标准测试流程模板 远端路径和本地路径必须分开执行。选择 $off-android-avd-ci-debug 时,后续 adb / llm_test_helper.py 都必须在能访问远端 emulator 的 off 环境中运行;选择本地 AVD 时才使用本机裸 adb 。远端交互入口不完整时可以改选本地 AVD,不能把远端 boot-check 后面接本机裸 adb 。 远端流程(选择 off 时) # 1. 先检查 off runner 健康状态 /Users/zhaoliyan/.agents/skills/off-android-avd-ci-debug/scripts/off-avd-ci-debug.sh status /Users/zhaoliyan/.agents/skills/off-android-avd-ci-debug/scripts/off-avd-ci-debug.sh boot-check # 2. boot-check 会清理模拟器;真实 UI 交互必须在 off runner 的远端 ADB 环境执行。 # 不要在本机继续执行裸 adb。需要设备命令时,用 ssh off 进入同一套远端环境: ssh off 'bash -lc ' "'" ' BASE=/home/dom/android-ci export JAVA_HOME="$BASE/java" export ANDROID_HOME="$BASE/android-sdk" export ANDROID_SDK_ROOT="$BASE/android-sdk" export ANDROID_USER_HOME="$BASE/android-home" export ANDROID_AVD_HOME="$BASE/avd" export ANDROID_EMULATOR_HOME="$BASE/emulator-home" export TMPDIR="$BASE/tmp" export PATH="$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator:$ANDROID_HOME/cmdline-tools/latest/bin:$PATH" adb devices ' "'" '' # 3. 验证结束后清理 /Users/zhaoliyan/.agents/skills/off-android-avd-ci-debug/scripts/off-avd-ci-debug.sh kill 本地流程(选择本地 AVD 时) # 1. 启动本地 AVD emulator -avd Medium_Phone_2 # 2. 启动应用 adb shell am force-stop com.github.zly2006.zhplus.lite adb shell monkey -p com.github.zly2006.zhplus.lite -c android.intent.category.LAUNCHER 1 sleep 10 # 3. 确认界面元素 python3 .agents/skills/ui-test/llm_test_helper.py dump # 4. 交互(根据 dump 结果选择命令) python3 .agents/skills/ui-test/llm_test_helper.py tap --tag nav_tab_hotlist # 5. 截图验证 python3 .agents/skills/ui-test/llm_test_helper.py screenshot /tmp/after_tap.png # (新 response 中)view /tmp/after_tap.png # 6. 滚动(无 tag 时) adb shell input swipe 540 1200 540 400 500 # 上滑 adb shell input swipe 540 400 540 1200 500 # 下拉刷新 已知 testTag 列表 底部导航栏(全局唯一,直接用 --tag) testTag 描述 nav_tab_home 主页 nav_tab_follow 关注 nav_tab_hotlist 热榜(可选,默认可能不显示) nav_tab_daily 日报 nav_tab_onlinehistory 历史 nav_tab_account 账号 Feed 卡片(每屏可能出现多个,必须配合 --within-text 或 --index) testTag 描述 每屏数量 feed_card 卡片主体(点击进入详情) 多个 feed_card_more_btn 卡片右上角更多菜单 多个,与 feed_card 一一对应 错误排查 错误前缀 含义 解决 [NOT FOUND] tag='xxx' 元素不在当前界面 先 dump 确认元素存在 [NOT FOUND] tag='xxx' APK 未更新 重新构建并 adb install -r [NOT FOUND] tag='xxx' 在包含...内不存在 --within-text 关键词不匹配 检查拼写,或改用 --index [AMBIGUOUS] tag='xxx' 匹配到 N 个 未消歧 ,脚本拒绝静默选第一个 按错误输出中的列表,加 --within-text 或 --index N 重试 [AMBIGUOUS] desc='xxx' 匹配到 N 个 --desc 出现歧义且不支持 --index 改用 --tag ,或改走 --text "" --index N [OUT OF RANGE] index=N --index 超出候选数量 先 find --tag xxx 确认数量,再选合法序号 uiautomator dump 失败 / adb pull dump 失败 ADB 异常或设备未连接 先执行 adb devices ,确认设备状态为 device 添加新 testTag Modifier.testTag( "my_new_tag" ) testTagsAsResourceId = true 已在 ZhihuMain.kt 根 Scaffold 启用,加 tag 后立即生效,将新 tag 补充到上方"已知 testTag 列表"。
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。