14 KiB
Android 测试常见问题与排障
WiFi 传输经验
- 原
mobile.transport是 BLE 计数对象,不能改为字符串。实际业务链路使用新增mobile.active_transport;以 BluezRuntime 组合后的状态测试,避免只测试 SessionManager 漏掉字段覆盖。 cmd wifi status的启用文字可能为Wifi或Wi-Fi,只在内存中忽略大小写与连字符后判断,不输出包含 SSID/IP 的原始内容。invokeOnCompletion不是协程异常处理器。网络监听的 collectLatest 内恢复屏障也可能因 BLE 已断开而失败;必须在 launch 主体捕获并结束会话,不能仅在完成回调做清理,否则可能断开成功后仍崩溃。- 网络回调取消不能截断正在发出的加密 BLE 消息。通道协商/撤销须有界地完成 BLE 交换,再响应取消;旧网络回调按注册实例隔离。
- 无线开关恢复分为“启用命令完成”和“网络实际可用”。测试先等关闭稳定,再启用并等待 Network 回调;一次重测通过不能单独证明此前恢复超时的根因。
- 模拟器冷启动超时不代表 Compose 测试失败。先检查已有 Emulator、加速能力和登记系统镜像,不重复下载;可用独立进程记录启动诊断、确认 boot_completed 后运行选定场景。只关闭本次启动实例。
测试前阅读本文件及 可重复测试流程。这里维护可复用的方法;单次失败、重测次数、耗时与验收结果写入 ../测试结果归档/。本页依据 四栏版真机记录 整理,方法有效不等于所有同类错误均有相同根因。
1. root 命令在 instrumentation 中失败
主机 ADB 的 su -c 检查通过,但 UiDevice.executeShellCommand("su -c '...'") 失败时,先检查命令解析。该入口不能假设经过交互 shell;字符串中的引号不保证按 shell 语法处理。已验证做法是调用短时上传的 LF shell 辅助文件,由文件内部执行 su -c "$*"。布局检查使用 authorized_root_command.sh;点击、滑动、编辑使用有前台限制的 authorized_app_input.sh。运行器结束清理手机临时文件。
区分命令构造错误与真实权限不足。真实 root/ADB/授权不可用时停止等待用户,不继续测试、不使用普通注入或无障碍动作替代。辅助文件只用于已授权的本软件调试,不扩大用途。
2. Windows 写出的 shell 文件无法执行
CRLF 会破坏 Android/Linux shell 的解释器或参数。生成 .sh 使用显式 UTF-8/LF(例如 Path.write_bytes,或文本写入指定 newline="\n"),不要依赖 Windows 文本默认换行。上传前检查不含 CRLF;Git 的 *.sh eol=lf 不能代替对本次生成文件的检查。不要因脚本解析失败反复请求 root。
3. 布局变更终止测试进程
在 instrumentation 运行中改变密度、字体或方向,可能使应用/测试进程重建或终止。不要把此类 Process crashed 直接当成产品崩溃,也不要在同一进程里继续依赖原窗口句柄。
使用 run_ui_layout_test.py:电脑端先保存原密度覆盖、字体和旋转设置,在每组测试启动前设置目标布局;测试启动后显式启动 Activity,再读取语义节点并执行 root 输入。电脑端 finally 在正常结束或失败时恢复原值,原设置不存在时删除对应项,原密度未覆盖时使用 reset。字体/方向回读核验;若新增 USB 保持唤醒等设置改动,同样必须先保存、恢复并核验,不以默认值猜测。安全锁屏不能正常解锁时等待用户,不绕过密码。
4. 窗口转储看不到控件、文字重复或节点不可点击
独立 uiautomator dump 在本机 MIUI 上曾无法稳定读取 App 控件。使用已验证的持久 instrumentation 入口读取语义节点;读取不是无障碍动作注入。不要盲点坐标,也不要因此改用无障碍点击。
Compose 的可见文字节点未必有 clickable 标志,导航“连接”也可能与扫描结果按钮同名。先限制 App 包、当前页面/条目容器,再筛选可见且边界非空的节点;底栏可按同名可见节点位置选择。检查边界在当前屏幕内,重新读取中心点后执行 root tap。等待页面加载完成再取位置,布局变化后不可复用旧坐标。列表滚动只在语义识别出的本 App 可见滚动区域内执行 root swipe。
5. 找不到 DHCP 开关或密码可见复选框
Compose 语义树不保证使用 android.widget.Switch/CheckBox 类名。定位标签附近的 checkable 节点:按标签实时纵向范围筛选,并结合行内左右位置区分 DHCP 开关与密码可见复选框。点击后检查 checked 状态或静态地址字段是否出现;不要只认按钮类名,也不能用一个任意 checkable 节点代替。
6. 文本未清空、中文/密码输入失败、返回键退出 App
Ctrl+A 在该测试环境下不可靠。现有做法:App 前台进程设置临时剪贴板,root 点击实时字段位置,按 MOVE_END,再按当前文本长度加余量执行有界 DEL,最后 root paste。清空操作计数有上限,输入后回读字段核验。剪贴板在 finally 清理,密码不放 ADB 参数、日志或公开转储中。
仅在输入法实际显示时发送 BACK 收起键盘;否则 BACK 可能退出页面。使用 helper 的 hide-keyboard 分支检查 mInputShown。等“屏幕方向”等设置数据就绪后才展开 WiFi 表单,避免数据加载改变控件位置。
7. 保存按钮的禁用断言失败
Compose 的禁用语义可能位于父节点,文字节点自身仍 enabled。检查文字所在控件及祖先链的 enabled 状态,并结合实际行为(空名称不能打开确认/提交)判断;不要只断言文字节点的 enabled。
8. 安装成功后权限又被 MIUI 重置
adb install 成功不证明蓝牙权限稳定。现有运行器在覆盖安装后通过 root 授予本 App 必需权限,等待 3 秒并回读;最多三轮,仍未稳定则停止等待用户。不能无限重试,不能修改其他系统安全开关。测试前仍检查登记、ADB、root、前台和必要权限。
9. 连续测试的 BLE 扫描或握手偶发失败
每个正常测试阶段结束时通过连接页显式断开,等待释放后再结束进程;不要只依赖紧接着的 force-stop。异常时按失败阶段记录扫描、GATT、握手/任务是否已开始,清理旧测试会话后重新扫描,不跨会话复用临时句柄。主机超时不会自动终止 instrumentation,运行器还需结束本 App 的旧测试进程。
确需核验板端服务恢复时,先确认手机已断开,再执行 check_mobile_lifecycle.py --restart-service;它会真实停启服务并核验运行目录、持久摘要和接口恢复。保留首次失败,恢复后通过不证明偶发扫描失败的根因。若重现持续存在,停止反复重启,针对具体阶段排查,不降低超时/断言来制造通过。
10. WiFi 专项不具备第二网络、错误密码时 SSH 断开
--validate-only、--wrong-only、--final-check 不要求电脑热点;错误密码单测使用当前受管网络。跨 SSID 的 DHCP/静态往返才需要第二个可用网络;缺少时标未验证,不拿重应用原网络或表单测试替代。
任何真实切网先保存受保护原 NetworkManager 配置,并核验定时恢复已建立。错误密码可能使 SSH 断开,继续通过 BLE 查看任务,等待定时恢复;连通后比较原配置摘要、活动网络与服务状态,再清理备份和定时器。网络恢复没有核验就不能写通过,也不能提前删除唯一恢复材料。
失败任务必须区分提交前握手失败与已经提交后的网络失败。“密码错误”只在可靠认证证据/结构化 AUTH_FAILED 下通过验收;超时、缺少 secret 或未知错误不能强行归类。确认密码未进入日志,清理手机私有文件和临时剪贴板,最后执行 --final-check。
11. 测试完成后的固定复盘
每轮检查:本轮有哪些失败/调整、是否已有可重复防范步骤、恢复是否核验、哪些原因仍未知。已验证解法更新本页和对应流程/构建说明;一次性证据留归档,不能将未证实推测写成固定根因。
最终反馈写明经验已更新的文档,以及尚未解决的问题或未验证边界。若没有新增经验,说明沿用现有方法即可,不复制重复条目。遵守根协作规则:不写真实凭据、手机标识、开发机绝对路径,文档更新后执行仓库卫生检查。
12. 轮询或滑动后节点失效、名称可见但按钮无法点击
本轮三种布局已验证:读取语义节点期间可能出现 StaleObjectException,应在原有有界期限内丢弃旧节点并重新查找,不复用旧坐标、不放宽断言。滚动定位使用 connection_list 的实时可见边界;扫描按钮还要限制在目标设备条目容器,检查按钮启用且 visibleBounds 非空。名称露出不证明兄弟按钮可见,空边界不能取中心点点击。
滑动后通过两次间隔400毫秒的实时边界相等检查确认目标停稳(最多5秒),然后仅发送一次 root 点击;不因未看到中间状态而重复点击连接。记录初次连接、连接中扫描、两处预览、条目断开、手动重连等阶段。短暂“连接中”未被观测不代表未发起请求,终态以认证连接和条目状态核验为准。
本轮失败、恢复与最终结果见 ../测试结果归档/2026-09-27_界面细节优化/;重测通过不证明此前连接未出现的唯一根因。字体、旋转和密度恢复后均回读核验。
13. 按影响选测与独立模拟器(2026-09-29)
- 先读 按影响选测,选中场景后才执行环境门禁。不能因为手机登记/网络不可用而阻塞不依赖它们的 JVM、模拟器或文档检查。需要真机但环境不可用时仍是“未验证”。
--list-scenarios/--dry-run不导入远端联调依赖、不访问凭据或 ADB。电脑系统 Python 未装 Paramiko 时,使用本机local_env.py setup ssh重建.local/ssh/venv并检查 import;不要给核桃派添加主机依赖。- com.android.test 插件已由同版本 AGP 放入 classpath 时,uiTest 使用无版本
id("com.android.test");显式重复版本可能导致 unknown version 冲突。uiTest 的 Compose 测试库与现有 Compose Multiplatform 锁定版本一致。 - 独立 uiTest 使用 self-instrumenting APK 和实际 Controller,不从反射篡改内部状态。fake RPC 必须遵循真实字段契约:内容条目需要 revision,缺失会在 thumbnailKey 中失败。此类夹具错误应修夹具,不弱化产品断言。
- 真机 navigation 临时撤销扫描/连接权限,防止已有记忆触发自动重连;finally 恢复原权限并回读,不访问板端身份。不将此场景用于权限允许/拒绝的产品验收。
- AVD 镜像 ZIP 手动解压不等于 SDK 包已登记。单独存放 SDK 时,avdmanager 必须定位同一 SDK 根;镜像 package.xml 保留官方 type-details/版本/许可证,复用已有 Emulator。优先使用 Android Studio SDK Manager 正常安装的包,不能靠反复下载解决根目录不一致。
- 模拟器测试出现失败,保留场景与配置结果,独立恢复字体、旋转、密度;只重跑受影响/未运行场景。失败不能记成全量通过。标准 Compose 输入仅适用于模拟器,登记真机仍用 root。
14. 内容预览在真实动画条目返回 BAD_REQUEST(2026-09-29)
真实用户动画的首帧可能是 path 指向持久图片,演示动画则可能是内嵌 image。新增 BLE 图片接口时要先检查 animations.playback_snapshot 的实际首帧结构,并沿设备既有路径验证与解码规则读取两种形式;不能把 path 当作无图或错误参数。空动画仍应按不可播放条目处理。复测须覆盖用户动画和演示动画,并做全库图片只读读取;本轮修正和实测见 内容缓存验收。
模拟器 AVD 名称若存在但启动提示系统目录不存在,先核对该名称的配置指向和镜像登记。保留旧配置,使用已安装镜像新建专用 AVD 再测试;不要因名称存在就反复启动,也不要擅自清空原 AVD。真机 instrumentation 前同时确认产品 APK 与 androidTest APK 已构建,只有测试 APK 时先补产品构建,再运行选中场景。
15. 项目本机环境迁移与中文路径(2026-10-01)
- 本项目专用 venv、AVD/系统镜像和私有主机状态使用 本机环境入口,不再依赖全局项目目录。旧全局 AVD 索引存在不代表 AVD 数据存在,先检查实际目录;缺失的数据和主机密钥不能写成迁移成功。
- venv 不能直接搬动后作为可移植环境:
pyvenv.cfg和入口脚本可能仍引用原位置。保留旧目录,用完整版本/哈希锁定 wheel 在新位置重建,再检查依赖与解释器。 - 本机 Emulator 在中文路径下报告
Could not write file、损坏的中文路径和无法读取 kernel;同一系统镜像通过 ASCII 目录联接启动后 settings/baseline 通过,确认本次启动失败属于路径访问问题。用local_env.py ui-smoke android自动创建短期入口,镜像/AVD 留在项目内,不移动到全局目录或再次下载镜像。临时入口结束后移除,AVD 的持久 image 路径恢复为项目内位置。 - AGP 构建入口传入 ASCII 目录联接时,不应先
resolve()展开为中文目标;build_android.py保留用户传入的 ASCII 拼写,构建实际写入项目.local/work/。只读路径解析使用常规 resolve,不把此规则扩展到其他环境。 - Emulator 可能把
config.ini重写成key = value,读取时应修剪键值空白,不能把格式变化误报为失效路径。复制项目后 setup 只刷新本工具管理的路径,保留用户数据。 - Windows Python 控制台在诊断输出包含替换字符时可能触发 GBK 编码错误;仅对本次 Python 进程使用
-X utf8,不全局调整系统设置。
单次启动失败与复测结果记录在 各种归档/2026-10-01_本机环境迁移/README.md;模拟器结果不代表任何真机或板端验收。