@harmonyos-arkts/d2h 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/.claude-plugin/marketplace.json +15 -13
  2. package/.claude-plugin/plugin.json +13 -7
  3. package/AGENTS.md +5 -5
  4. package/README.md +212 -212
  5. package/agents/android-to-hmos-00-orchestrator.md +318 -318
  6. package/agents/d2h.md +157 -157
  7. package/dist/bin/install-opencode.js +30 -30
  8. package/docs/environment-check.md +86 -86
  9. package/install-opencode.sh +160 -160
  10. package/opencode/agents.json +16 -16
  11. package/opencode/vscode-d2h-package.json +7 -7
  12. package/opencode/vscode-d2h-plugin.mjs +29 -29
  13. package/package.json +54 -54
  14. package/schemas/android-source-manifest.schema.json +25 -25
  15. package/schemas/checkpoint-provenance.schema.json +67 -67
  16. package/schemas/final-acceptance.schema.json +29 -29
  17. package/schemas/managed-evidence-index.schema.json +15 -15
  18. package/schemas/managed-evidence.schema.json +114 -114
  19. package/schemas/migration-config.schema.json +51 -51
  20. package/schemas/migration-report-index.schema.json +39 -39
  21. package/schemas/migration-report-item.schema.json +51 -51
  22. package/schemas/migration-report-summary.schema.json +25 -25
  23. package/schemas/migration-status.schema.json +202 -202
  24. package/schemas/preflight.schema.json +60 -60
  25. package/schemas/source-order-audit.schema.json +16 -16
  26. package/schemas/source-provenance-event.schema.json +19 -19
  27. package/schemas/spec-app-shard.schema.json +45 -45
  28. package/schemas/spec-fact-corrections-shard.schema.json +13 -13
  29. package/schemas/spec-features-shard.schema.json +43 -43
  30. package/schemas/spec-index.schema.json +26 -26
  31. package/schemas/spec-interactions-shard.schema.json +40 -40
  32. package/schemas/spec-page.schema.json +98 -98
  33. package/schemas/spec-pages-index.schema.json +1 -1
  34. package/schemas/spec-unresolved-shard.schema.json +1 -1
  35. package/schemas/task-envelope.schema.json +109 -109
  36. package/schemas/task-plan.schema.json +341 -341
  37. package/scripts/check-environment.mjs +320 -320
  38. package/skills/android2hmos_resources_convert/SKILL.md +180 -180
  39. package/skills/android2hmos_resources_convert/references/image-conversion-rules.md +230 -230
  40. package/skills/android2hmos_resources_convert/references/svg-fix-patterns.md +175 -175
  41. package/skills/android2hmos_resources_convert/references/xml-drawable-to-svg-rules.md +513 -513
  42. package/skills/arkts-app-identity/SKILL.md +238 -238
  43. package/skills/arkts-i18n/SKILL.md +496 -496
  44. package/skills/arkts-i18n/evals/evals.json +84 -84
  45. package/skills/arkts-i18n/references/code-examples.md +302 -302
  46. package/skills/arkts-i18n/references/common-pitfalls.md +391 -391
  47. package/skills/arkts-i18n/references/dynamic-language-switch.md +604 -604
  48. package/skills/arkts-i18n/references/hardcoded-string-scanner.md +348 -348
  49. package/skills/arkts-i18n/references/language-codes.md +104 -104
  50. package/skills/arkts-i18n/references/resource-file-structure.md +775 -775
  51. package/skills/arkts-i18n/references/static-vs-dynamic.md +242 -242
  52. package/skills/arkts-i18n/references/v1-compat.md +244 -244
  53. package/skills/arkts-i18n/scripts/audit_i18n_completeness.sh +174 -174
  54. package/skills/arkts-icon-sizing/SKILL.md +211 -211
  55. package/skills/arkts-icon-sizing/scripts/icon_audit.py +131 -131
  56. package/skills/arkts-icon-sizing/scripts/icon_autofix.py +88 -88
  57. package/skills/arkts-icon-sizing/scripts/icon_dims.py +179 -179
  58. package/skills/arkts-icon-sizing/scripts/icon_fix.py +119 -119
  59. package/skills/arkts-mvvm-architecture/SKILL.md +613 -613
  60. package/skills/d2h-hypium-forge/SKILL.md +309 -309
  61. package/skills/d2h-hypium-forge/references/functional-spec-template.md +140 -140
  62. package/skills/d2h-hypium-forge/references/official-api.md +135 -135
  63. package/skills/d2h-hypium-forge/references/pitfalls.md +98 -98
  64. package/skills/d2h-hypium-forge/references/testability-template.md +71 -71
  65. package/skills/d2h-hypium-forge/scripts/_common_template.py +659 -659
  66. package/skills/d2h-hypium-forge/scripts/analyze_results.py +165 -165
  67. package/skills/d2h-hypium-forge/scripts/assert_audit.py +107 -107
  68. package/skills/d2h-hypium-forge/scripts/collect_runtime_pages.py +169 -169
  69. package/skills/d2h-hypium-forge/scripts/forge_report.py +325 -325
  70. package/skills/d2h-hypium-forge/scripts/inject_resource_ids.py +114 -114
  71. package/skills/d2h-hypium-forge/scripts/lint_asserts.py +80 -80
  72. package/skills/d2h-hypium-forge/scripts/lint_locate.py +60 -60
  73. package/skills/d2h-hypium-forge/scripts/merge_appgraph.py +249 -249
  74. package/skills/d2h-hypium-forge/scripts/precondition.py +140 -140
  75. package/skills/d2h-hypium-forge/scripts/preinject_ids.py +232 -232
  76. package/skills/d2h-hypium-forge/scripts/probe.py +197 -197
  77. package/skills/d2h-hypium-forge/scripts/run_direct.py +823 -823
  78. package/skills/d2h-hypium-forge/scripts/run_parallel.py +121 -121
  79. package/skills/d2h-hypium-forge/scripts/scan_features.py +255 -255
  80. package/skills/d2h-hypium-forge/scripts/upgrade_asserts.py +66 -66
  81. package/skills/d2h-hypium-forge/scripts/validate_scenarios.py +84 -84
  82. package/skills/d2h-page-develop/SKILL.md +112 -112
  83. package/skills/d2h-page-develop/agents/openai.yaml +7 -7
  84. package/skills/d2h-page-spec-generate/SKILL.md +206 -206
  85. package/skills/d2h-page-spec-generate/scripts/build_batch_report.py +227 -227
  86. package/skills/d2h-utg-ai-generate/SKILL.md +128 -128
  87. package/skills/d2h-utg-ai-generate/references/click-paths-schema.json +76 -76
  88. package/skills/d2h-utg-ai-generate/references/extraction-guide.md +34 -34
  89. package/skills/d2h-utg-ai-generate/references/facts-contract.md +96 -96
  90. package/skills/d2h-utg-ai-generate/references/page-schema.json +61 -61
  91. package/skills/d2h-utg-ai-generate/references/utg-schema.json +89 -89
  92. package/skills/d2h-utg-ai-generate/scripts/build_page_json.py +314 -314
  93. package/skills/d2h-utg-ai-generate/scripts/build_utg.py +123 -123
  94. package/skills/d2h-utg-ai-generate/scripts/capture_from_page_json.ts +280 -280
  95. package/skills/d2h-utg-ai-generate/scripts/utg_common.py +524 -524
  96. package/skills/d2h-utg-ai-generate/scripts/utg_html.py +489 -489
  97. package/skills/d2h-utg-ai-generate/scripts/validate_utg.py +69 -69
  98. package/skills/d2h-utg-ai-generate/scripts/vendor/D3-LICENSE +13 -13
  99. package/skills/d2h-utg-ai-generate/scripts/vendor/d3-7.9.0.min.js +2 -2
  100. package/skills/d2h-utg-ai-generate/tests/test_pipeline.py +369 -369
  101. package/skills/d2h-utg-static-generate/SKILL.md +73 -73
  102. package/skills/d2h-utg-static-generate/references/discoveries.md +38 -38
  103. package/skills/d2h-utg-static-generate/scripts/generate.py +499 -499
  104. package/skills/d2h-utg-static-generate/tests/test_static.py +335 -335
  105. package/skills/d2h-utg-static-generate/tests/verify-offline-html.py +60 -60
  106. package/skills/d2h-utg-static-generate/tests/verify-produced-fixture.py +131 -131
  107. package/skills/harmonyos-migration-playbook/SKILL.md +83 -83
  108. package/skills/harmonyos-migration-playbook/agents/openai.yaml +7 -7
  109. package/skills/harmonyos-migration-playbook/references/arkts-compile.md +24 -24
  110. package/skills/harmonyos-migration-playbook/references/harmony-runtime.md +53 -53
  111. package/skills/harmonyos-migration-playbook/references/lesson-lifecycle.md +45 -45
  112. package/skills/harmonyos-migration-playbook/references/protocol-e2e.md +23 -23
  113. package/skills/harmonyos-migration-playbook/references/ui-automation.md +53 -53
  114. package/skills/harmonyos-migration-playbook/references/windows-environment.md +38 -38
  115. package/skills/maintaining-migration-report/SKILL.md +144 -144
  116. package/skills/maintaining-migration-report/references/final-acceptance.md +48 -48
  117. package/skills/maintaining-migration-report/references/source-provenance.md +66 -66
  118. package/skills/managing-d2h-toolchain/SKILL.md +24 -24
  119. package/skills/managing-d2h-toolchain/environment-requirements.json +16 -16
  120. package/skills/managing-d2h-toolchain/scripts/manage-toolchain.mjs +98 -98
  121. package/skills/managing-d2h-toolchain/toolchain.json +16 -16
  122. package/skills/native-library-substitution/SKILL.md +384 -384
  123. package/skills/native-library-substitution/references/native-library-substitution.json +56905 -56905
  124. package/skills/native-library-substitution/references/native-library-substitution.md +163 -163
  125. package/skills/preparing-migration-workspace/SKILL.md +131 -131
  126. package/skills/reviewing-migration-process/SKILL.md +62 -62
@@ -1,98 +1,98 @@
1
- # Hypium 高频踩坑清单(7 项目实证 + 官方文档修正)
2
-
3
- 来源:agc-template-market 7 个项目(DailySchedule/CarBeautyCare/Recipes/HomeDecoration/WebShortDrama/Recycling/DigitalNewspaper)白盒开发全记录。完整数据见 TestDemo 仓库 `reports/HYPIUM-DEV-COST-ANALYSIS.md`。
4
-
5
- ## 框架/API 层
6
-
7
- ### 1. `swipe` distance 是百分比(4/7 项目首踩)
8
- `driver.swipe(direction, distance)` 的 distance 是**滑动区域总长的 1%-100%**,非像素。按像素写 250 会越界报 invalid/负坐标。direction 用常量 `UiParam.LEFT/RIGHT/UP/DOWN`。精确滑动用 `slide(start, end)`;长滑抽屉类(swipeAction 露出按钮)要 ~40% 屏宽。
9
-
10
- ### 2. `BY.text` 默认全匹配(5/7 项目)
11
- 模板文案(`${used}看过`)、mock 长标题("非常好吃上头的的可乐鸡翅~~")全匹配必失败。**修正**:`MatchPattern.CONTAINS`(官方支持,无需自写子串遍历——早期项目自写了 find_text_contains,其实框架原生支持)。还支持 STARTS_WITH/ENDS_WITH/REGEXP/REGEXP_ICASE。
12
-
13
- ### 3. `press_back()` 语义不唯一(RCY 6 次失败中 3 次)
14
- 收软键盘与 pop 页面不区分:编辑页上收键盘会把整页 pop 掉。**绕法**:点击页面标题空白处失焦收键盘。框架暂无 dismiss_keyboard()。
15
-
16
- ### 4. 系统子窗口对组件树不可见(6/7 项目)
17
- Toast(promptAction)、系统权限弹窗、输入法窗口、MapKit 级联面板均拿不到。**对策**:Toast 断言改界面持久变化;权限弹窗用 `hdc shell atm` 预授权或 setup 处理一次;输入法遮挡按钮→先收键盘再点。**A 线(LLM 截图)反而能读 Toast**——融合分工点。
18
-
19
- ### 5. 视口外控件(2/7 项目)
20
- 不需要手工滑动!`touch(BY.text("xx"), scroll_target=BY.type("Scroll"))` 与 `check_component_exist(..., scroll_target=...)` 原生支持滚动查找。仅当控件被布局裁剪出屏(如 CBC_008 `height('100%')` 缺陷)才完全不可达→登记应用缺陷+降级断言。
21
-
22
- ### 6. DatePicker/滚轮无列级 API(2/7)
23
- 几何坐标模拟:取 DatePicker bounds 右侧 15% 处为日列中心,小距离 swipe 后**读取高亮值校验,过冲则反向回滑一格**(闭环纠偏)。
24
-
25
- ### 7. Rect/bounds 便捷方法缺失(3/7)
26
- 无 get_left 等;用 get_center()/get_size() 或直接 r.left/r.right 字段。`.id()` 不一定暴露(应用没写 test id 时);Span 拼接文本拿不到完整串→用父 Text CONTAINS。
27
-
28
- ### 8. `input_text` 行为细节
29
- 默认**先清空再输入**;中文走剪贴板一次粘贴;英文 <200 字符逐键。粘贴板输入后软键盘可能不弹出——某些校验依赖输入事件的表单要留意。
30
-
31
- ## 应用/数据层
32
-
33
- ### 9. PersistenceV2 登录态跨用例残留(RCY 6 次失败的另一半)
34
- "not in logout state" 类失败的根因。**标准解**:setup 里 `driver.clear_app_data(PACKAGE)`(官方 API)或 `hdc shell bm clean -n <pkg> -d`,然后重新 mock_login。
35
-
36
- ### 10. 纯内存数据不可跨用例继承
37
- VM 里普通数组(如地址列表)每次启动为空——同用例 setup 内造数,勿依赖其他用例。
38
-
39
- ### 11. 华为账号 Kit 模拟器必失败
40
- 模板 app 普遍有模拟登录降级:一键登录失败 → 弹"是否先模拟登录成功?/温馨提示" → 点确认 → isLogin=true。common 库封装 `mock_login()`,注意有的要先勾协议 Checkbox(软键盘可能遮挡它——先收键盘)。
41
-
42
- ### 12. press_back 的另一面:Web 页面 go_back 被 Web 历史消费
43
- 详情页是 Web 组件时,press_back 先退 Web 历史;EMBEDDED sheet 返回首页后不自动关闭会遮挡底栏——回首页后显式关 sheet。
44
-
45
- ### 13. 异步导航延迟(WSD-014 flaky)
46
- 登录成功后 app 数秒后自动跳首页,会把校验通过的页面"带走"。**标准解**:每步操作前 `ensure_page()` 自愈式重进。
47
-
48
- ### 14. 同名控件歧义
49
- 订单状态 Tab 与卡片状态文案同名→按 y 最小取顶部;弹窗"取消"与顶栏"取消"→按 y 区分或用 within/inWindow 缩范围。
50
-
51
- ### 15. mock 数据语义陷阱
52
- 搜索可能是 `name 子串 || labels 精确`(热词"华为手机"零命中,"手机"命中 labels);列表最新在前;首条地址自动设默认。**读 mock/VM 源码是唯一可靠途径**。
53
-
54
- ## 执行器层(harmonyrun)
55
-
56
- ### 16. 全量模式 xdevice bug
57
- `harmonyrun hypium run .`(不带 --case)报 "Test source 'testcases' does not exist"——即使 cwd 正确。只能 `--case XXX_001` 逐条,每条 ~40s 框架开销(安装/报告),15 条多花 ~7min。
58
-
59
- ### 17. 必须先 cd 到 hypium 项目目录
60
- 相对路径解析依赖 cwd;后台命令的 cd 不影响后续 shell——写 run.sh 固定 cwd。
61
-
62
- ### 18. 报告位置
63
- xdevice 报告在 `<项目>/reports/<时间戳>/`,summary_report.html / report_data.json(逐条耗时在 report_data.json)。控制台管道 tail 会截日志,排障去报告目录取全量日志。
64
-
65
- ## SchoolLife 对照实验新增(2026-09-16,N1~N10)
66
-
67
- ### 19. isAfter/isBefore 是"整体在上方/下方",非同行左右
68
- 表单同行布局(label 左、输入框右)用 isAfter 定位会命中下一行的框。同行控件用 y 区间过滤或 within(容器);xpath `//TextInput[n]` 序号 >1 不可用。
69
-
70
- ### 20. 组件树包含被 sheet/弹窗遮挡的背景控件
71
- sheet 打开时背景页控件仍可被 find 命中,点击打在遮挡层上。弹窗内操作前先断言弹窗标题存在,或校验目标 bounds 是否被遮挡。
72
-
73
- ### 21. AlertDialog 文本命中返回整窗容器
74
- 点容器中心未必命中按钮。用 find_all 取容器内 Button 子控件再点。
75
-
76
- ### 22. 坐标是 px 不是 vp(vp×3.5)
77
- 源码 vp 尺寸直接当坐标用会全偏。common 库封装 vp→px 换算;无文字图标按钮先几何过滤再算中心。
78
-
79
- ### 23. BY.text 的 MatchPattern 必须位置传参
80
- `BY.text(match_pattern=MatchPattern.CONTAINS)` 关键字传参被拒,必须 `BY.text(s, MatchPattern.CONTAINS)`。
81
-
82
- ### 24. input_text 偶发不生效
83
- 封装"输入后 getText 回读校验 + 重试"。
84
-
85
- ### 25. 用例间业务数据冲突
86
- 带唯一性/重叠校验的功能(如课程时段),每条用例分配互斥数据;全套重跑前卸载重装或 clear_app_data。
87
-
88
- ### 26. 功能被登录态门控但用例集未体现
89
- control-facts 阶段必须查每个功能入口的 isLogin 分支(SchoolLife 签到需"模拟关联"后才能用)。
90
-
91
- ### 27. 模拟器锁屏/崩溃无预案会报废整轮
92
- 每次 setup 先亮屏(press_key POWER / 检查 display 状态),崩溃后重试;atm perm 预授权在部分镜像不存在,勿依赖。
93
-
94
- ### 28b. 权限弹窗保护规则(用户指令 2026-09-16)
95
- 执行中出现任何权限确认弹窗(位置/相机/麦克风/相册/通知,"允许/仅本次允许/禁止"),**一律点击同意/允许继续**——除非该用例明确设计为"无权限状态下的测试"(如验证拒绝后的降级 UI/引导页)。落法:common 库 launch/setup 加弹窗处理循环(检测弹窗文案→点允许→重检到无弹窗)。注意系统权限弹窗是系统子窗口、组件树可能不可见(见 #4),不可见时用坐标点击或 `hdc shell atm` 预授权兜底。
96
-
97
- ### 28. key 定位现状:模板 app 几乎无 .id()
98
- 实测 8 项目 .id() 密度 0~9 处(集中在个别安全组件)。遇到有 id 的模块优先 BY.key(SchoolLife 签到 4 条一次通过即证据);脚本生成时输出"可测性改造建议"(给关键控件打语义化 .id())作为交付物之一。
1
+ # Hypium 高频踩坑清单(7 项目实证 + 官方文档修正)
2
+
3
+ 来源:agc-template-market 7 个项目(DailySchedule/CarBeautyCare/Recipes/HomeDecoration/WebShortDrama/Recycling/DigitalNewspaper)白盒开发全记录。完整数据见 TestDemo 仓库 `reports/HYPIUM-DEV-COST-ANALYSIS.md`。
4
+
5
+ ## 框架/API 层
6
+
7
+ ### 1. `swipe` distance 是百分比(4/7 项目首踩)
8
+ `driver.swipe(direction, distance)` 的 distance 是**滑动区域总长的 1%-100%**,非像素。按像素写 250 会越界报 invalid/负坐标。direction 用常量 `UiParam.LEFT/RIGHT/UP/DOWN`。精确滑动用 `slide(start, end)`;长滑抽屉类(swipeAction 露出按钮)要 ~40% 屏宽。
9
+
10
+ ### 2. `BY.text` 默认全匹配(5/7 项目)
11
+ 模板文案(`${used}看过`)、mock 长标题("非常好吃上头的的可乐鸡翅~~")全匹配必失败。**修正**:`MatchPattern.CONTAINS`(官方支持,无需自写子串遍历——早期项目自写了 find_text_contains,其实框架原生支持)。还支持 STARTS_WITH/ENDS_WITH/REGEXP/REGEXP_ICASE。
12
+
13
+ ### 3. `press_back()` 语义不唯一(RCY 6 次失败中 3 次)
14
+ 收软键盘与 pop 页面不区分:编辑页上收键盘会把整页 pop 掉。**绕法**:点击页面标题空白处失焦收键盘。框架暂无 dismiss_keyboard()。
15
+
16
+ ### 4. 系统子窗口对组件树不可见(6/7 项目)
17
+ Toast(promptAction)、系统权限弹窗、输入法窗口、MapKit 级联面板均拿不到。**对策**:Toast 断言改界面持久变化;权限弹窗用 `hdc shell atm` 预授权或 setup 处理一次;输入法遮挡按钮→先收键盘再点。**A 线(LLM 截图)反而能读 Toast**——融合分工点。
18
+
19
+ ### 5. 视口外控件(2/7 项目)
20
+ 不需要手工滑动!`touch(BY.text("xx"), scroll_target=BY.type("Scroll"))` 与 `check_component_exist(..., scroll_target=...)` 原生支持滚动查找。仅当控件被布局裁剪出屏(如 CBC_008 `height('100%')` 缺陷)才完全不可达→登记应用缺陷+降级断言。
21
+
22
+ ### 6. DatePicker/滚轮无列级 API(2/7)
23
+ 几何坐标模拟:取 DatePicker bounds 右侧 15% 处为日列中心,小距离 swipe 后**读取高亮值校验,过冲则反向回滑一格**(闭环纠偏)。
24
+
25
+ ### 7. Rect/bounds 便捷方法缺失(3/7)
26
+ 无 get_left 等;用 get_center()/get_size() 或直接 r.left/r.right 字段。`.id()` 不一定暴露(应用没写 test id 时);Span 拼接文本拿不到完整串→用父 Text CONTAINS。
27
+
28
+ ### 8. `input_text` 行为细节
29
+ 默认**先清空再输入**;中文走剪贴板一次粘贴;英文 <200 字符逐键。粘贴板输入后软键盘可能不弹出——某些校验依赖输入事件的表单要留意。
30
+
31
+ ## 应用/数据层
32
+
33
+ ### 9. PersistenceV2 登录态跨用例残留(RCY 6 次失败的另一半)
34
+ "not in logout state" 类失败的根因。**标准解**:setup 里 `driver.clear_app_data(PACKAGE)`(官方 API)或 `hdc shell bm clean -n <pkg> -d`,然后重新 mock_login。
35
+
36
+ ### 10. 纯内存数据不可跨用例继承
37
+ VM 里普通数组(如地址列表)每次启动为空——同用例 setup 内造数,勿依赖其他用例。
38
+
39
+ ### 11. 华为账号 Kit 模拟器必失败
40
+ 模板 app 普遍有模拟登录降级:一键登录失败 → 弹"是否先模拟登录成功?/温馨提示" → 点确认 → isLogin=true。common 库封装 `mock_login()`,注意有的要先勾协议 Checkbox(软键盘可能遮挡它——先收键盘)。
41
+
42
+ ### 12. press_back 的另一面:Web 页面 go_back 被 Web 历史消费
43
+ 详情页是 Web 组件时,press_back 先退 Web 历史;EMBEDDED sheet 返回首页后不自动关闭会遮挡底栏——回首页后显式关 sheet。
44
+
45
+ ### 13. 异步导航延迟(WSD-014 flaky)
46
+ 登录成功后 app 数秒后自动跳首页,会把校验通过的页面"带走"。**标准解**:每步操作前 `ensure_page()` 自愈式重进。
47
+
48
+ ### 14. 同名控件歧义
49
+ 订单状态 Tab 与卡片状态文案同名→按 y 最小取顶部;弹窗"取消"与顶栏"取消"→按 y 区分或用 within/inWindow 缩范围。
50
+
51
+ ### 15. mock 数据语义陷阱
52
+ 搜索可能是 `name 子串 || labels 精确`(热词"华为手机"零命中,"手机"命中 labels);列表最新在前;首条地址自动设默认。**读 mock/VM 源码是唯一可靠途径**。
53
+
54
+ ## 执行器层(harmonyrun)
55
+
56
+ ### 16. 全量模式 xdevice bug
57
+ `harmonyrun hypium run .`(不带 --case)报 "Test source 'testcases' does not exist"——即使 cwd 正确。只能 `--case XXX_001` 逐条,每条 ~40s 框架开销(安装/报告),15 条多花 ~7min。
58
+
59
+ ### 17. 必须先 cd 到 hypium 项目目录
60
+ 相对路径解析依赖 cwd;后台命令的 cd 不影响后续 shell——写 run.sh 固定 cwd。
61
+
62
+ ### 18. 报告位置
63
+ xdevice 报告在 `<项目>/reports/<时间戳>/`,summary_report.html / report_data.json(逐条耗时在 report_data.json)。控制台管道 tail 会截日志,排障去报告目录取全量日志。
64
+
65
+ ## SchoolLife 对照实验新增(2026-09-16,N1~N10)
66
+
67
+ ### 19. isAfter/isBefore 是"整体在上方/下方",非同行左右
68
+ 表单同行布局(label 左、输入框右)用 isAfter 定位会命中下一行的框。同行控件用 y 区间过滤或 within(容器);xpath `//TextInput[n]` 序号 >1 不可用。
69
+
70
+ ### 20. 组件树包含被 sheet/弹窗遮挡的背景控件
71
+ sheet 打开时背景页控件仍可被 find 命中,点击打在遮挡层上。弹窗内操作前先断言弹窗标题存在,或校验目标 bounds 是否被遮挡。
72
+
73
+ ### 21. AlertDialog 文本命中返回整窗容器
74
+ 点容器中心未必命中按钮。用 find_all 取容器内 Button 子控件再点。
75
+
76
+ ### 22. 坐标是 px 不是 vp(vp×3.5)
77
+ 源码 vp 尺寸直接当坐标用会全偏。common 库封装 vp→px 换算;无文字图标按钮先几何过滤再算中心。
78
+
79
+ ### 23. BY.text 的 MatchPattern 必须位置传参
80
+ `BY.text(match_pattern=MatchPattern.CONTAINS)` 关键字传参被拒,必须 `BY.text(s, MatchPattern.CONTAINS)`。
81
+
82
+ ### 24. input_text 偶发不生效
83
+ 封装"输入后 getText 回读校验 + 重试"。
84
+
85
+ ### 25. 用例间业务数据冲突
86
+ 带唯一性/重叠校验的功能(如课程时段),每条用例分配互斥数据;全套重跑前卸载重装或 clear_app_data。
87
+
88
+ ### 26. 功能被登录态门控但用例集未体现
89
+ control-facts 阶段必须查每个功能入口的 isLogin 分支(SchoolLife 签到需"模拟关联"后才能用)。
90
+
91
+ ### 27. 模拟器锁屏/崩溃无预案会报废整轮
92
+ 每次 setup 先亮屏(press_key POWER / 检查 display 状态),崩溃后重试;atm perm 预授权在部分镜像不存在,勿依赖。
93
+
94
+ ### 28b. 权限弹窗保护规则(用户指令 2026-09-16)
95
+ 执行中出现任何权限确认弹窗(位置/相机/麦克风/相册/通知,"允许/仅本次允许/禁止"),**一律点击同意/允许继续**——除非该用例明确设计为"无权限状态下的测试"(如验证拒绝后的降级 UI/引导页)。落法:common 库 launch/setup 加弹窗处理循环(检测弹窗文案→点允许→重检到无弹窗)。注意系统权限弹窗是系统子窗口、组件树可能不可见(见 #4),不可见时用坐标点击或 `hdc shell atm` 预授权兜底。
96
+
97
+ ### 28. key 定位现状:模板 app 几乎无 .id()
98
+ 实测 8 项目 .id() 密度 0~9 处(集中在个别安全组件)。遇到有 id 的模块优先 BY.key(SchoolLife 签到 4 条一次通过即证据);脚本生成时输出"可测性改造建议"(给关键控件打语义化 .id())作为交付物之一。
@@ -1,71 +1,71 @@
1
- # 可测试性需求(Design for Testability)— 模板与累积清单
2
-
3
- > 调测中发现的「让 hypium 测试变慢/不准」的工程特征,反哺为对应用开发的需求。
4
- > 每条格式:现象(实测) → 根因 → 可测试性需求(对开发的要求) → 收益。
5
-
6
- ## 累积清单(按工程验证时追加)
7
-
8
- ### DFT-001 控件必须预置稳定 ID
9
- - 现象:无 .id() 控件用 BY.text 定位,文案随数据变化 → 脚本重试多轮、不稳定(实测:首个转化工程首轮全部超时)。
10
- - 根因:ArkTS 开发普遍省略 .id(),uitest 只能按 text/type 匹配。
11
- - 需求:**所有可交互控件(Button/Toggle/TextInput/入口 Image)必须写 .id()**,命名 `<语义>_<页面>`(如 btn_settings_index)。
12
- - 收益:脚本零重试定位;用例与实现解耦(文案改了脚本不断)。
13
-
14
- ### DFT-002 条件渲染控件需可达路径
15
- - 现象:`if(testMode)` 内控件默认态不存在,存在性断言误报失败(实测 START TEST 按钮)。
16
- - 需求:条件功能的入口开关应在**入口页可达**(≤2 步操作),或提供 deeplink/want 参数直达。
17
- - 收益:状态覆盖用例可自动执行,不依赖复杂前置链。
18
-
19
- ### DFT-003 运行时权限在模拟器的可预授性
20
- - 现象:首启权限弹窗阻塞 BFS/用例执行(实测 RaiseToAnswer 电话权限)。
21
- - 需求:应用不应在首帧同步弹多个权限弹窗;权限申请延后到功能触发点。
22
- - 收益:precondition 批量预授后用例零弹窗干扰。
23
-
24
- ### DFT-004 登录需提供测试通道
25
- - 现象:真实登录页在模拟器无法自动完成 → 登录后功能全部 BLOCKED。
26
- - 需求:提供 mock 登录开关(want 参数/环境开关)或测试账号常量。
27
- - 收益:登录态用例可全自动执行。
28
-
29
- ### DFT-005 首启弹窗需可编程处置
30
- - 现象:隐私协议/引导页弹窗文案各异,逐个适配成本高。
31
- - 需求:首启弹窗按钮文案使用标准词(同意并继续/跳过/我知道了);提供"不再提醒"。
32
- - 收益:统一 dismiss 片段即可覆盖。
33
-
34
- (新工程验证时按编号追加,注明来源工程与实测数据)
35
-
36
- ### DFT-006 HAP 更新必须卸载重装(模拟器缓存怪癖)
37
- - 现象:`install -r` 同版本号替换后,注入的 .id 运行时全部丢失(abc 缓存不失效,实测 News 工程)。
38
- - 需求/skill 规则:**注入 ID 重打包后一律 `hdc uninstall <bundle> && hdc install <hap>`**。
39
-
40
- ### DFT-007 部分 HAR 模块 .id 运行时丢弃(待官方解释)
41
- - 现象:同一 HAP 内 commons/features-home 的 .id 生效,features-mine 的全部不生效(abc 字节串在、属性指令无效,跨 4 种注入位置复现)。
42
- - 需求:**smart_check/smart_click 必须带 orig_target 文本兜底**(key 失败转文本/类型断言)。
43
- - 来源:News 工程(2026-09-23 实测)。
44
-
45
- ### DFT-008 同控件多次注入会叠 id(仅首个生效)
46
- - 现象:多条用例引用同一控件时注入器产生 `.id(a).id(b)`,运行时仅第一个可查。
47
- - 需求/skill 规则:**用例引用统一到首注入 ID(`_1` 后缀规约)**;注入器应检测已有 tc_ id 并复用。
48
-
49
- ### DFT-009 Tab 切换的可靠路径
50
- - 现象:BY.text 精确/模糊点击 Tab 均可能点到正文同名文本;比例坐标受 Tab 数量与手势条影响。
51
- - 需求/skill 规则:**click_tab 用 find_all_components 取「最靠下的同名文本」的 bounds 中心 touch**(News/SchoolLife/CoolMall 2/3/4-Tab 全验证通过)。
52
-
53
- ### DFT-010 资源化文案使静态覆盖度失准
54
- - 现象:CoolMall(70k 行)源码文案全部 `$r()` 资源化,scan 的交互点与运行时文本不匹配 → 静态覆盖度 0%。
55
- - 需求/skill 规则:大型工程覆盖度评估降级为**运行时可达性口径**(用例通过率 + dump 文本对照);源码覆盖度仅对硬编码文案工程有效。
56
-
57
- ### DFT-011 用例间需间歇(teardown 冷启动时序)
58
- - 现象:批量连跑时下一条 setup 的 start_app 未完成即断言(TC01 偶发失败)。
59
- - skill 规则:批量执行循环 **sleep 3s** + launch 等待 2.5s 起步。
60
-
61
- ### DFT-012 输入法首用向导是隐藏前置(CoolMall 实测)
62
- - 现象:input_text 前拉起「小艺输入法」声明弹窗 + 键盘布局向导(多步),挡住输入与提交按钮;向导期间点登录无效。
63
- - skill 规则:precondition 增加 IME 预置步骤——检测并依次点掉「同意/下一步/完成」;输入后 **press_back 收键盘再点提交按钮**(否则按钮被键盘遮挡)。
64
-
65
- ### DFT-013 输入框定位用 BY.hint 不用 BY.text
66
- - 现象:`BY.text('请输入手机号')` 匹配到的是 hint 展示文本节点而非 TextInput 本体,input_text 无效且无报错。
67
- - skill 规则:**带占位符的输入框一律 `BY.hint('<placeholder>')` 定位**(hypium 专属匹配器)。
68
-
69
- ### DFT-014 设备访问 PC mock 需 rport(fport 是反向)
70
- - 现象:`hdc fport` 是 PC→设备方向;设备 App 访问 127.0.0.1:8787 的 PC mock 必须用 `hdc rport tcp:8787 tcp:8787`(CoolMall BASE_URL 已预指 mock)。
71
- - 附:mock 重启后 App 需 aa force-stop 冷启动才重新拉数据(失败态有缓存)。
1
+ # 可测试性需求(Design for Testability)— 模板与累积清单
2
+
3
+ > 调测中发现的「让 hypium 测试变慢/不准」的工程特征,反哺为对应用开发的需求。
4
+ > 每条格式:现象(实测) → 根因 → 可测试性需求(对开发的要求) → 收益。
5
+
6
+ ## 累积清单(按工程验证时追加)
7
+
8
+ ### DFT-001 控件必须预置稳定 ID
9
+ - 现象:无 .id() 控件用 BY.text 定位,文案随数据变化 → 脚本重试多轮、不稳定(实测:首个转化工程首轮全部超时)。
10
+ - 根因:ArkTS 开发普遍省略 .id(),uitest 只能按 text/type 匹配。
11
+ - 需求:**所有可交互控件(Button/Toggle/TextInput/入口 Image)必须写 .id()**,命名 `<语义>_<页面>`(如 btn_settings_index)。
12
+ - 收益:脚本零重试定位;用例与实现解耦(文案改了脚本不断)。
13
+
14
+ ### DFT-002 条件渲染控件需可达路径
15
+ - 现象:`if(testMode)` 内控件默认态不存在,存在性断言误报失败(实测 START TEST 按钮)。
16
+ - 需求:条件功能的入口开关应在**入口页可达**(≤2 步操作),或提供 deeplink/want 参数直达。
17
+ - 收益:状态覆盖用例可自动执行,不依赖复杂前置链。
18
+
19
+ ### DFT-003 运行时权限在模拟器的可预授性
20
+ - 现象:首启权限弹窗阻塞 BFS/用例执行(实测 RaiseToAnswer 电话权限)。
21
+ - 需求:应用不应在首帧同步弹多个权限弹窗;权限申请延后到功能触发点。
22
+ - 收益:precondition 批量预授后用例零弹窗干扰。
23
+
24
+ ### DFT-004 登录需提供测试通道
25
+ - 现象:真实登录页在模拟器无法自动完成 → 登录后功能全部 BLOCKED。
26
+ - 需求:提供 mock 登录开关(want 参数/环境开关)或测试账号常量。
27
+ - 收益:登录态用例可全自动执行。
28
+
29
+ ### DFT-005 首启弹窗需可编程处置
30
+ - 现象:隐私协议/引导页弹窗文案各异,逐个适配成本高。
31
+ - 需求:首启弹窗按钮文案使用标准词(同意并继续/跳过/我知道了);提供"不再提醒"。
32
+ - 收益:统一 dismiss 片段即可覆盖。
33
+
34
+ (新工程验证时按编号追加,注明来源工程与实测数据)
35
+
36
+ ### DFT-006 HAP 更新必须卸载重装(模拟器缓存怪癖)
37
+ - 现象:`install -r` 同版本号替换后,注入的 .id 运行时全部丢失(abc 缓存不失效,实测 News 工程)。
38
+ - 需求/skill 规则:**注入 ID 重打包后一律 `hdc uninstall <bundle> && hdc install <hap>`**。
39
+
40
+ ### DFT-007 部分 HAR 模块 .id 运行时丢弃(待官方解释)
41
+ - 现象:同一 HAP 内 commons/features-home 的 .id 生效,features-mine 的全部不生效(abc 字节串在、属性指令无效,跨 4 种注入位置复现)。
42
+ - 需求:**smart_check/smart_click 必须带 orig_target 文本兜底**(key 失败转文本/类型断言)。
43
+ - 来源:News 工程(2026-09-23 实测)。
44
+
45
+ ### DFT-008 同控件多次注入会叠 id(仅首个生效)
46
+ - 现象:多条用例引用同一控件时注入器产生 `.id(a).id(b)`,运行时仅第一个可查。
47
+ - 需求/skill 规则:**用例引用统一到首注入 ID(`_1` 后缀规约)**;注入器应检测已有 tc_ id 并复用。
48
+
49
+ ### DFT-009 Tab 切换的可靠路径
50
+ - 现象:BY.text 精确/模糊点击 Tab 均可能点到正文同名文本;比例坐标受 Tab 数量与手势条影响。
51
+ - 需求/skill 规则:**click_tab 用 find_all_components 取「最靠下的同名文本」的 bounds 中心 touch**(News/SchoolLife/CoolMall 2/3/4-Tab 全验证通过)。
52
+
53
+ ### DFT-010 资源化文案使静态覆盖度失准
54
+ - 现象:CoolMall(70k 行)源码文案全部 `$r()` 资源化,scan 的交互点与运行时文本不匹配 → 静态覆盖度 0%。
55
+ - 需求/skill 规则:大型工程覆盖度评估降级为**运行时可达性口径**(用例通过率 + dump 文本对照);源码覆盖度仅对硬编码文案工程有效。
56
+
57
+ ### DFT-011 用例间需间歇(teardown 冷启动时序)
58
+ - 现象:批量连跑时下一条 setup 的 start_app 未完成即断言(TC01 偶发失败)。
59
+ - skill 规则:批量执行循环 **sleep 3s** + launch 等待 2.5s 起步。
60
+
61
+ ### DFT-012 输入法首用向导是隐藏前置(CoolMall 实测)
62
+ - 现象:input_text 前拉起「小艺输入法」声明弹窗 + 键盘布局向导(多步),挡住输入与提交按钮;向导期间点登录无效。
63
+ - skill 规则:precondition 增加 IME 预置步骤——检测并依次点掉「同意/下一步/完成」;输入后 **press_back 收键盘再点提交按钮**(否则按钮被键盘遮挡)。
64
+
65
+ ### DFT-013 输入框定位用 BY.hint 不用 BY.text
66
+ - 现象:`BY.text('请输入手机号')` 匹配到的是 hint 展示文本节点而非 TextInput 本体,input_text 无效且无报错。
67
+ - skill 规则:**带占位符的输入框一律 `BY.hint('<placeholder>')` 定位**(hypium 专属匹配器)。
68
+
69
+ ### DFT-014 设备访问 PC mock 需 rport(fport 是反向)
70
+ - 现象:`hdc fport` 是 PC→设备方向;设备 App 访问 127.0.0.1:8787 的 PC mock 必须用 `hdc rport tcp:8787 tcp:8787`(CoolMall BASE_URL 已预指 mock)。
71
+ - 附:mock 重启后 App 需 aa force-stop 冷启动才重新拉数据(失败态有缓存)。