一小时深入随机模拟器测试
结论
2026-10-25 的搜索红屏修复与复验见文末;以下保留 2026-10-24 的原始测试结论。
本次不能整体判为通过:确认一项 P1 搜索退出红屏,另有一次模拟器窗口系统阻塞。 普通编辑、保存重开、撤销重做、草稿恢复和 Unicode 的实际内容核对通过;大文件全文自动读取未完成。
- 主测试窗口:20:13:32.575–21:13:34.838,墙钟 3,602.26 秒(1 小时 2 秒)。
- 包含基线、随机操作、故障定位、模拟器恢复;过程有中断,详见阶段表。
- 补充边界检查至 21:19:11.145;全部设备测试与诊断窗口为 1 小时 5 分 39 秒。
- 18 类随机工作流共尝试 466 次,462 次完整完成,4 次中断。
- 中断分别为按钮与提示条定位歧义、系统窗口阻塞、搜索红屏及取消按钮坐标未命中。
- 搜索红屏另外做了三次独立复现,3/3 失败。
- 记录 1,120 次断言:1,119 次通过,1 次因 XML 丢失 emoji 误判;无损 RPC 复核通过。
- 这些是重复工作流中的实际核对次数,并非 1,120 项独立功能。
- 工作流超时、红屏和无法读取的检查另行报告,不因未形成失败断言就算通过。
- 业务源码未修改;原测试提交内容只有报告与三张证据截图,2026-10-25 补充定位歧义截图
117.png。
环境与方法
- 日期:2026-10-24;本文操作时间为 Asia/Shanghai,Android logcat 与 VM 原始事件为 UTC。
- 源码基准:
9bf4c143f63a2e8ed0fcc8bf6f1d05fee1fc4b28;测试前 Git 工作区干净。 - 本次重新构建当前源码并通过
adb install -r安装,未清除应用数据。 - APK:Android x64 Debug,
com.mynote.mynote_mobile,版本0.1.0+1。 - APK SHA-256:
DAC0E329C0A8ACA0ABAAADCA79FBB54AEA67329F9D8AD28F5FB89401A0962A19。 - 设备:
emulator-5554,AVDt1,Android 15 / API 35,x86_64,320 × 640,160 dpi。 - 使用项目已有
test/ui/driver.py、E01–E04 与 EP01–EP16 作为基线。 - 随机测试使用可记录的固定种子,随机选择完整工作流,并核对完整编辑器正文与实际磁盘文件。
- 通过 ADB、uiautomator2、截图、XML、磁盘正文和 Flutter VM 事件交叉检查。
- 使用独立本地测试库,不执行远端同步、登录、原有仓库删除或原有笔记编辑。
- 原始证据与临时测试工具位于
build/qa-hour/,未提交到 Git;flutter clean会删除它们。 - 主随机种子:
2026102420;恢复后扩展种子:2026102421。 - 测试库
QA-UI-2d92c0b062-1,目录 IDb2f67a42f3a58ae388c95efbf5a8740a,保留数据供复查。- 第一段另建测试库 ID
24e634801c9280d77a7f2d7f62527104,同样保留。
- 第一段另建测试库 ID
- 结束后恢复原自动旋转设置与原输入法,停止本次 VM 采集并移除本次端口转发。
阶段与覆盖
| 阶段/证据目录 | 结果 | 说明 |
|---|---|---|
初始 build/qa-hour/ |
39 次核对通过;2 次随机尝试 | 36 项基线通过;横竖屏后的同名提示条定位歧义中断 |
continued/ |
149 次核对通过;53 次随机尝试 | 再次通过 36 项基线;第 53 轮系统窗口阻塞 |
resumed/ |
2 次恢复核对通过;1 次随机尝试 | 模拟器重启后数据一致;搜索退出红屏 |
search-repro/ |
搜索红屏 3/3 复现 | VM 捕获首发控制器释放错误与后续连锁异常 |
extended/ |
907 次核对通过;410 次随机尝试 | 运行 45 分 2.68 秒;取消按钮坐标未命中一次,恢复后继续 |
deep/ |
4 次夹具核对通过,1 次工具误判 | XML 用句点代替 emoji;改用直接文本 RPC 复核 |
deep-verified/ |
4 次夹具核对通过;前置模式等待超时 | 已打开标签保留编辑模式;后续显式切换预览再测 |
deep-final/ |
11 次核对通过 | Unicode 输入保存恢复、长文通过;大文件全文读取受阻 |
deep-tail/ |
3 次核对通过 | 大文件磁盘不变;异常 Markdown 源码与磁盘一致 |
随机操作尝试次数
| 操作 | 次数 | 操作 | 次数 |
|---|---|---|---|
| 进程重启 | 34 | 横竖屏往返 | 35 |
| 关闭未保存笔记并取消 | 11 | 普通预览滚动 | 27 |
| 前后台切换 | 23 | 追加正文/Markdown | 31 |
| 打开关闭大纲 | 21 | 显式保存流程 | 32 |
| 保存、关闭、重开 | 34 | 打开关闭笔记菜单 | 23 |
| 撤销重做流程 | 32 | 预览切换 | 28 |
| 搜索退出 | 1 | 打开关闭收藏夹 | 28 |
| 密集手势 | 28 | 双指手势 | 31 |
| 标签往返 | 22 | 文件筛选弹窗取消 | 25 |
每轮结束切回编辑模式核对完整正文,并读取 preview.md 检查最后一次保存版本。
密集手势每轮注入 15 次内容区滑动,共 420 次;双指手势每轮一放一缩,共 62 次。
操作次数包含中断尝试;搜索路径确认故障后不再纳入后续随机池,关闭取消路径在坐标问题后停用。
边界内容
| 文件 | 原始大小 | 检查结果 |
|---|---|---|
unicode.md |
54 字符,108 UTF-8 字节 | 中文、emoji、ZWJ 家庭字符、组合字符、开头空行;无损读取、插入、保存和重启恢复通过 |
long.md |
57,997 字符,61,297 字节,300 个标题 | 预览滚动、切换源码、全文逐字与磁盘核对通过 |
huge.md |
560,027 字符,805,027 字节 | 超过高亮阈值;预览滚动和编辑画面可见,磁盘逐字不变;全文 RPC 未完成 |
malformed.md |
103 字符,110 字节 | 缺失图片、表格、未知语言和未闭合代码块;预览、源码与磁盘核对通过 |
Unicode 插入通过测试工具注入,不代表真实中文输入法的候选词与组合态交互已经覆盖。 Unicode 源码截图。
性能观察
扩展随机阶段采集 14,668 条 Flutter.Frame,单位已从微秒转换为毫秒。
VM 连接在进程重启后重新建立,样本不覆盖每个启动最早的帧;下表不作为完整 FPS 统计。
| 指标 | 中位数 | P95 | 最大值 |
|---|---|---|---|
| Flutter 构建 | 3.063 ms | 29.136 ms | 974.025 ms |
| Flutter 光栅 | 78.680 ms | 256.589 ms | 1,980.416 ms |
| Flutter 帧事件 elapsed | 153.336 ms | 480.934 ms | 2,321.215 ms |
- 12,870 / 14,668 条光栅样本超过 16.667 ms,约 87.74%;本次环境渲染偏慢,不判流畅性通过。
- 83 次应用 PSS 内存采样:347.91–412.25 MiB,中位数 380.84 MiB。
- 这些样本跨多个重启后的进程,不能用来证明长期无泄漏。
- 设备为 Debug 模拟器,EGL 为
emulation,系统 HWUI 为skiagl;不将这些值外推到真机 Release。 - 原始帧事件:
vm-events.jsonl;内存与 Android 窗口帧统计:extended/sample-*.txt。
已确认问题
P1:关闭搜索弹层导致红屏
- 独立复现:3/3;另在随机扩展测试中首次发现一次。
- 前置条件:笔记处于编辑模式,点击正文使键盘出现。
- 操作:点击顶栏“搜索笔记”,按 Android 返回键,约 350 ms 后再次按返回键,等待退出。
- 预期:收起键盘与搜索弹层,回到笔记;正文保持不变。
- 实际:编辑界面消失并出现红屏,需要重启应用恢复。
- Flutter VM 捕获的首发错误:
A TextEditingController was used after being disposed.。 - 首发错误控件:
TextField,lib/search_actions.dart:66:30。 - 随后出现
_dependents.isEmpty、attached、错误构建作用域及大幅布局溢出等连锁断言。- 这些后续异常不重复计为多个独立缺陷。
- 代码检查:
_showSearch在await showModalBottomSheet返回后立即query.dispose(),见第 153 行。- 判断:弹层退出过渡尚未卸载输入框,控制器已被释放;与首发调用栈一致。
- 本次只记录测试结果,未修改业务代码,也未验证修复。
- 原始证据:
build/qa-hour/vm-events.jsonl、search-first-error.txt、search-repro/。 - 红屏截图。
环境异常:Android 窗口系统长时间阻塞
- 2026-10-25 后续独占复测已重现同类 watchdog 与任务截图阻塞,见 复现检查报告。
- 发生时间:20:21:10 发起应用重启,20:22:39 左右界面树调用才返回,耗时 89.50 秒。
- 发生位置:第一段随机测试第 53 轮
restart,此前 149 项断言通过。 - Android 出现
system_server_pre_watchdog;转储记录窗口、显示、动画线程阻塞 15 秒及 74 秒。 - 动画线程位于
BpSurfaceComposer::captureLayersSync→ScreenCapture.captureLayers→ 任务截图路径。 - 期间窗口服务曾不可用,应用停留在 Flutter 启动画面;重启模拟器后恢复。
- 此证据表明存在 Android 系统截图/窗口链路阻塞,不能据此认定为 Dart 应用崩溃。
- 重启模拟器后,使用故障前 XML 保存的完整正文与磁盘核对,两项均通过。
- 原始证据:
system-pre-watchdog.txt、system-watchdog.txt、lastanr.txt、continued/logcat.txt。 dumpsys activity lastanr未报告应用 ANR;本次分别报告系统 watchdog 与应用红屏。
待查:大文件源码无障碍节点缺失
huge.md有 560,027 个 Unicode 字符,约 595,027 个 UTF-16 单元,超过 524,288 的高亮阈值。- 预览进入并执行八次滚动后,切换编辑模式,截图能看到正确源码及键盘。
- 此时 XML 无
android.widget.EditText,直接getText也报UiObjectNotFoundError。 - 大文件相关界面树采样分别耗时约 5.09 秒和 9.38 秒,明显慢于普通笔记。
- 没有捕获新增 Flutter 异常,磁盘与原始夹具逐字一致,但未证明编辑器内全文完整。
- 当前证据无法区分 Android/uiautomator 大文本可访问性限制与应用语义输出问题,保留为待查。
- 不把大文件编辑、保存、草稿恢复判为通过;本次没有向该大文件输入或保存。
- 大文件编辑画面,证据
deep-final/029.xml与deep-final-console.txt。
测试工具与观察边界
- 第一段测试遇到“编辑”按钮与同名提示条的定位歧义,见失败截图
117.png。- 原图位于
build/qa-hour/117.png,此前仅保留在被 Git 忽略的构建目录,未随报告提交;现已补充到报告附件目录。 - 同次
117.xml中两个节点的content-desc均为“编辑”:工具栏按钮可点击,底部提示条不可点击。 - 驱动仅按名称匹配,抛出
Ambiguous UI label: 编辑;截图本身不是应用错误画面。 - 临时随机驱动改为优先匹配可点击节点,未修改项目正式驱动或业务代码。
- 原图位于
- 本次 uiautomator 界面树 XML 导出链路对非 BMP 字符的表示有损,并非 XML 格式不支持这些字符。
- BMP 是 Unicode 基本多文种平面;
📝(U+1F4DD)位于其外,在 UTF-16 中占两个编码单元。 - 原始
build/qa-hour/deep/009.xml中📝变为..,家庭 emoji 的各个非 BMP 字符也变为..,ZWJ 连接符仍保留。 - 首次断言将 XML 节点的
text与原文逐字比较,因此失败;原始失败仍见build/qa-hour/deep-console.txt。 - 截图显示正确;后续绕过 XML 导出,用
uiautomator2的get_text()(直接控件getTextRPC)读取并与原文逐字核对,通过。 build/qa-hour/deep-final-console.txt记录全文读取、Unicode 插入、UTF-8 保存及重启恢复核对均通过,故判定首次失败为工具误判。- 此结论限于本次已复核的 Unicode 夹具,未定位导出链路中具体替换字符的实现层;后续 Unicode 核对统一使用直接文本 RPC。
- BMP 是 Unicode 基本多文种平面;
- 新建测试库后,驱动在切库忙碌期间立即检查名称,出现初始化提示;不能据此确认切库失败。
- 扩展随机第 121 轮的“关闭取消”等待超时:键盘收起导致对话框下移,
点击使用 XML 中的旧坐标
(98, 218),最终截图中按钮已位于约y=365。- 确认框仍正常显示,没有对应 VM 异常;不计为已确认产品缺陷。
- 证据:
extended/624.xml、extended/665.png与动作时间线。 - 重启后完整源码与磁盘的恢复核对均通过;后续随机关闭取消路径停用,其他路径继续。
- 弹层打开/取消只证明该路径可进出及数据未变,不代表全部筛选规则与收藏增删已覆盖。
- 双指与密集手势检查核对模式恢复和数据完整性,不对手势锚点像素精度作通过承诺。
- 运行中会强制停止并恢复进程;内存样本跨越多个进程,不能据此证明长期无内存泄漏。
- Debug 模拟器的帧数据只代表本次环境,不替代真机 Profile/Release 性能验证。
静态、单元与工具检查
| 检查 | 结果 |
|---|---|
flutter analyze |
1 条既有 info:test/mp3_refresh_view_test.dart:37:11,if 语句缺少花括号 |
flutter test |
376 项通过 |
py -3 -m unittest discover -s test/ui -p "test_*.py" |
24 项通过;输出内含工具单元测试故意产生的内层失败样本,外层结果为 OK |
flutter build apk --debug --target-platform android-x64 |
成功 |
| 安装当前构建 APK | 成功 |
构建前按项目要求设置当前进程的 jdk.net.unixdomain.tmpdir,未修改全局 Java 配置。
Gradle 输出 SDK XML 版本提示,但本次构建成功。
未覆盖
- iOS、其他 Android 版本、真机及 Release 性能。
- 远端同步冲突、在线音频、实际录音、摄像头、蓝牙与语音识别服务。
- 本次测试期间不修复发现的产品缺陷。
- 大文件全文读取、编辑保存与恢复,以及真实中文输入法组合态仍需进一步验证。
证据入口
build/qa-hour/summary.json:各阶段断言、随机尝试、VM 异常与性能汇总。- 各目录
actions.jsonl:带时间戳的注入操作、观察与断言。 - 各目录编号
.png/.xml:实际界面与无障碍树;横屏截图另外以随机轮次命名。 build/qa-hour/search-repro-console.txt:三次独立搜索退出复现结果。build/qa-hour/search-first-error.txt:首发 Flutter 控制器异常及完整堆栈。build/qa-hour/analyze.txt、flutter-test.txt、python-tests.txt:检查原始输出。build/qa-hour/soak.py、deep.py、finish.py、metrics.py:本次临时工具与随机种子。
2026-10-25 搜索红屏修复与复验
- 搜索输入框自行管理控制器,只在搜索逻辑中保留查询字符串。
- 控制器随输入框卸载释放,避免弹层退出动画和键盘尺寸变化时访问已释放的控制器。
- 保留原查询代次校验、错误处理、草稿搜索和结果定位。
- 新增
test/search_sheet_test.dart三项组件回归,修复前全部复现原控制器错误,修复后通过。- 覆盖返回、点击遮罩、点击搜索结果三种退出路径,并在退场动画中改变键盘 inset。
- 核对未保存草稿、磁盘不变、结果跳转、再次打开查询为空及清空查询后的空状态。
- 全量
flutter test:379 项通过。 flutter analyze:仍为原有的test/mp3_refresh_view_test.dart:37:11花括号 info,无新增问题。- 当前源码的 Android x64 Debug APK 构建、安装成功。
- 共享模拟器正被其他任务反复重启应用,设备复验改用独立临时
emulator-5556。- Android 15 / API 35,320 × 640,160 dpi,使用新建的隔离测试库。
- 按原步骤开启编辑键盘、打开搜索、间隔约 350 ms 按两次返回,空查询与有查询交替测试。
- 五次独立进程启动复验全部通过,包含初始化在内共 14 项设备断言通过。
- Flutter VM 采集覆盖复验,未出现
Flutter.Error;每次完整正文与磁盘均保持一致。
- 本次证据:
build/search-before.txt、build/search-full-test.txt、build/search-analyze.txt, 以及build/search-fix/isolated/中的动作、截图、断言和 VM 事件。 - 本节仅关闭搜索红屏问题;原报告中的大文件全文验证与系统窗口阻塞不属于本次修复范围。
