AI_UIAutomation/prompts/must_test_conversion.md

13 KiB
Raw Blame History

必测项 → 自动化 转换提示词(子提示词)

配合主提示词使用。本文件只覆盖「必测项」专项的特殊处理(来源、结构、映射、双协议、step 级回写)。 通用规则——技术栈 / DeviceDriver 接口 / 脚本模板 / 元素发现工作流 / 边跑边写调试 / 失败截图 / 报告——一律遵循 prompts/ones_to_automation.md,此处不重复。 冲突时,以本子提示词的「必测项专项」约定为准。


1. 必测项来源(ONES)

  • 团队 98Q19ZsW(sz.ones.cn)
  • 测试计划:必测项-AI自动化 plan uuid CQz9YCNX
  • 用例库:App 必测项 library uuid EPfZfC9Y(97 条)
  • ones 二进制:/Users/woan/local/bin/ones
  • 读取:
    # 列表(注意:list 不返回 steps)
    /Users/woan/local/bin/ones testcase case list EPfZfC9Y
    # 单条完整步骤(控制用例必须用这个拿 steps)
    /Users/woan/local/bin/ones testcase case search --key 15974   # WiFi控制设备
    /Users/woan/local/bin/ones testcase case search --key 15975   # 蓝牙控制设备
    

2. 必测项的两种结构(转换前必须理解)

必测项不是一种新用例,而是两类已有维度的「视图」:

A. 添加(connect)—— 按单品,每型号一条 case

  • 分布在品类模块(摄像头/灯&WiFi/蓝牙/开关/URC HUB/温湿度&hub/Lock/扫地机 类),约 73 条「添加X验证」。
  • 每条 ONES case → 一个设备的添加流程 → 落到 tests/<cat>/<device>_connect.test.ts
  • 主键 = ONES 用例号(number)。

B. 控制(control)—— 2 条超级用例,按连接协议分组,每个 step = 一个单品的核心控制

ONES 名称 步数 前置条件
15975 (uuid Lqpkx6mp) 蓝牙控制设备 49 关 WiFi/热点、开蓝牙
15974 (uuid Vp7vuhbu) WiFi控制设备 56 开 WiFi/热点、关蓝牙
  • 控制粒度在 step,不在 case。主键 = (ones_number, step_uuid)
  • 同一设备(Bot/Lock/Curtain/Meter…)在两条里都出现 → 两个控制断言(不同协议)。
  • camera / robot / osc 只在 WiFi 出现(本身是 WiFi 设备)。
  • 控制内容不止开关:meter 温湿度校正、camera 出流停留 3min、robot 清扫/暂停/回充、Humidifier2 绑温湿度计、curtain/roller 百分比。
  • 落到对应设备的 tests/<cat>/<device>_control.test.ts(多数断言主提示词流程里已存在)。

C. 非单品(本次不转,除非用户要求)

~12 条平台级:登录/房间/消息中心/场景/覆盖安装。归 tests/automation/ 或平台用例,不在「各单品添加+控制」范围。


3. 落点原则

必测是「视图」,不是「副本」。不要新建 tests/必测/ 目录。 每条必测项映射到已有的 {device}_connect.test.ts(添加) / {device}_control.test.ts(控制),用标记 + manifest去选,而不是搬代码。这与「步骤沉到 utils/common.test.ts 只做薄编排」一致。


4. 品类模块 → 仓库目录映射

ONES 模块 仓库目录
摄像头类 camera(出流类也可拆 osc)
灯类&WiFi ceiling_light / strip_light / color_bulb / humidifier / air_condition
蓝牙类 curtain / sensor / fan / remote
开关类 plug(含 Relay Switch / Garage Door)
URC HUB hub / urc / bot
温湿度&hub类 meter / hub / sensor
Lock类 lock / keypad
扫地机类 robot

设备名取 config/device.config.tsDEVICE_CONFIG,不要在脚本里写死。


5. 映射 manifest(核心产物)

生成 test-plan/must-test.manifest.ts,作为「ONES 必测项 ↔ 代码 ↔ 回写 ↔ 覆盖率」的中间层。双主键:添加按 case,控制按 step。

// test-plan/must-test.manifest.ts —— 由 scripts/gen-must-test-manifest.ts 从 ONES 生成,勿手改
export type MustTestItem =
  | { kind: 'add';  ones: number; name: string; cat: string; device: string;
      file: string; testName: string; status: 'done'|'todo'|'na' }
  | { kind: 'ctrl'; ones: 15974|15975; step: string; proto: 'wifi'|'ble';
      name: string; cat: string; device: string; action: string;
      file: string; testName: string; status: 'done'|'todo'|'na' };

export const MUST_TEST: MustTestItem[] = [
  { kind:'add',  ones:91013, name:'添加Plug验证', cat:'plug', device:'Plug 4D',
    file:'tests/plug/plug_connect.test.ts', testName:'[P0] 通过BLE添加Plug', status:'todo' },
  { kind:'ctrl', ones:15974, step:'<stepUuid>', proto:'wifi', name:'点击控制Plug 开/关',
    cat:'plug', device:'Plug 4D', action:'开/关',
    file:'tests/plug/plug_control.test.ts', testName:'[P0][ble+wifi] 开/关 Plug', status:'todo' },
  // ... 全部 添加 case + 两条控制用例的全部 step
];

生成脚本要点(scripts/gen-must-test-manifest.ts):

  1. case list EPfZfC9Y → 取全部「添加X验证」case(模块属品类) → 生成 kind:'add' 行。
  2. case search --key 15974/15975 → 遍历 steps[],每步生成 kind:'ctrl' 行,带 step.uuid / proto / 从 desc 解析的 device+action
  3. 用第 4 节映射表填 cat,用 DEVICE_CONFIGdevice,推断目标 file
  4. status 初始 todo,实现后由测试运行结果回填(见第 9 节)。

6. P0 标记约定(带 ONES 锚点)

关键:锚点必须打在 reporter.record(名称, ...) 的名称里——结果写入 reports/.results.json 用的是 record 名称,buildAnchoredPayloads 从中解析 [ONES:号(#step)] 做回写。it() 标题里也加同一锚点作备注(测试报告里可见、便于追溯),但回写不读 it 标题。

// it 标题:加 [ONES:号] 作备注(可读/可追溯)
it(`[ONES:15968] 通过BLE添加${deviceName}设备`, async () => {
  // ...
  // reporter.record 名称:加 [P0][ONES:号] —— 这是回写真正依据
  reporter.record(`[P0][ONES:15968] 添加${deviceName}`, 'PASS', dur, detail);
});

// 控制(协议相关):record 名称带 用例号#step_uuid + 协议;协议由 PROTO 环境变量切(见 §7)
const CTRL = process.env.PROTO === 'wifi' ? '[P0][ONES:15974#<step>][wifi]' : '[P0][ONES:15975#<step>][ble]';
reporter.record(`${CTRL} 开/关 ${deviceName}`, status, dur, detail);
  • 一条 ONES step 可由多个用例覆盖 → 用同一 step 锚点,回写自动聚合(fail>skip>pass)。
  • 筛选:vitest -t '\[P0\]'(全量) / 结果文件里按 [ble]/[wifi] 区分协议。

同品类多型号:设备维度动态锚点

一个品类的脚本只测默认设备,但同品类多个 UI 相似型号(如 Curtain/Curtain3/BlindTilt)应共用脚本、各自回写。不要写死 ONES 号,改用 utils/common/ones-anchor.helper.ts 按当前设备动态解析:

import { onesAdd, onesCtrl } from '../../utils/common';
const ADD_ANCHOR = onesAdd('curtain', deviceName);     // 添加: 按 CURTAIN_DEVICE 解析
const CTRL_CURTAIN = onesCtrl('curtain', deviceName);  // 控制: 按设备 + PROTO 解析
reporter.record(`${ADD_ANCHOR} 添加窗帘设备`, ...);
  • ANCHORS map(在 ones-anchor.helper.ts)按 品类 → 设备名(DEVICE_CONFIG) → {add, ctrlBle, ctrlWifi} 维护;新增型号补一行即可
  • 跑法:<CAT>_DEVICE 环境变量按型号多跑几遍(× PROTO),每遍写到该型号的 ONES 用例。
    CURTAIN_DEVICE='Curtain3 2B' PROTO=ble npx vitest run tests/curtain
    
  • 约束:每个型号要是账号里真实存在的设备才能跑(变体覆盖上限 = 真机数量)。
  • UI 不相似的型号(需新写)→ 单独脚本 + 自己的锚点,不走此复用。

7. 双协议运行模式(本次确定:双协议覆盖)

控制必测两种协议都要跑,以与 ONES 的两条用例 1:1 对齐。协议是运行模式,靠前置切换手机网络:

  • PROTO=ble:关 WiFi/热点、开蓝牙 → 跑所有 [ble] 控制(对应 15975)
  • PROTO=wifi:开 WiFi/热点、关蓝牙 → 跑所有 [wifi] 控制(对应 15974)
  • 切换动作优先 adb(Android)/串口;无法自动化时,按 feedback-manual-navigation 让用户手动切换并确认后继续。
  • 仅在该协议下存在的设备(camera/robot/osc 只在 wifi)才生成对应模式的断言。
// package.json
"test:must:add":       "vitest run -t '\\[P0\\].*添加'",
"test:must:ctrl:ble":  "PROTO=ble  vitest run -t '\\[P0\\].*\\[ble\\]'",
"test:must:ctrl:wifi": "PROTO=wifi vitest run -t '\\[P0\\].*\\[wifi\\]'",
"test:must":           "npm run test:must:add && npm run test:must:ctrl:ble && npm run test:must:ctrl:wifi"

8. 控制 step → 断言 转换规则

每个 step 是「操作 + 预期」,转成该设备 control 测试里的一条断言:

  • step.desc = 操作(如「点击控制Bot 不加密开&不加密关&加密按压」)→ 拆成对应控制动作序列。
  • step.result = 预期(如「对应Bot固件响应动作」)→ 断言(状态变更 / UI 反馈 / 出流成功 / 图表加载)。
  • 复杂控制按设备类型走既有 helper:开关类用控制 helper;meter 校正走设置页校正流程;camera 出流后停留 3min再断言画面/水印;robot 断言清扫/暂停/回充状态。
  • 多数动作主提示词的 control 流程已实现 → 复用,不重写;仅补必测特有断言并打 P0 锚点。

9. step 级结果回写 ONES正确方法GraphQL mutation

⚠️ 必须走 ones graphql mutation,不要用 curl 直连 REST .../cases/update ones config show 会把 token 打码成 ***,curl 直连必然 401 AuthFailure.InvalidToken; 而 ones graphql 复用 CLI 登录认证、无需 token/PAT,且已在权限白名单内。 此机制已在 utils/ones-sync.tspostPayloads 实现,跑 scripts/sync-ones-results.ts 即用。

key 拼接规则(确定式)

  • case: testcase_plan_case-<planUUID>-<caseUUID>
  • step: testcase_plan_case_step-<planUUID>-<caseUUID>-<stepUuid>

写入 mutation

# case 级
ones graphql 'mutation { updateTestcasePlanCase(key: "testcase_plan_case-CQz9YCNX-<caseUUID>", result: "passed") { key } }'
# step 级result 字段名是 step_result不是 execute_result/result
ones graphql 'mutation { updateTestcasePlanCaseStep(key: "testcase_plan_case_step-CQz9YCNX-<caseUUID>-<stepUuid>", step_result: "passed", actual_result: "开/关成功") { key } }'
  • result / step_result 取值:passed / failed / skipped / to_do(PASS→passed、FAIL→failed、SKIP→skipped)。

必测项据此:

  • 按用例聚合、一趟写完(批量规则):同一用例的所有 step 结果先聚合,在一次回写流程里写完该用例的全部 step、再写 case 级 result——不要把一个用例的步骤分散到多次回写里逐个触发。(buildAnchoredPayloads 已按 caseUUID 聚合 step,postPayloads 对一个用例的 steps 连续写完再写 case,即满足此规则。GraphQL 不支持单请求多 mutation,故实现上是同一趟内连续多次 mutation,效果即"一次性更新该用例多个步骤"。)
  • 添加/功能 case:只写 case 级 updateTestcasePlanCase
  • 控制用例 15974 / 15975:case 级 result 由 step 聚合(全跑完才 passed/failed,否则 to_do)。[ble]→15975、[wifi]→15974。
  • 匹配靠测试名 [ONES:号#step] 锚点(已在 buildAnchoredPayloads 实现),不用 LCS 误配。

回写参数已固化(用例固定、仅新增):test-plan/ones-writeback-params.json 保存了计划全部用例(号→uuid)+ 15974/15975 的步骤 uuid。用例与步骤 uuid 与具体计划无关,plan UUID 是回写时唯一变量——后续给定任意必测项 plan 链接,取出 planUUID 即可按上面 key 规则拼出所有 case/step key 直接回写,无需重新查 ONES。用例新增后重跑 npm run gen:writeback-params 刷新。

读回校验:

ones graphql '{ testcasePlanCaseSteps(filter: { testcasePlan: { uuid_in: ["CQz9YCNX"] }, testcaseCase: { uuid_in: ["<caseUUID>"] } }, limit: 60) { key stepResult actualResult } }'

(注意:查询用驼峰 stepResult/actualResult,filter 用 testcasePlan/testcaseCase 嵌套 uuid_in。)


10. 覆盖率核对

用 manifest 对照 ONES 必测清单,产出未实现列表:

  • add 行:哪些「添加X」还没有对应 _connect 测试。
  • ctrl 行:两条用例共 105 步,哪些 step 还没对应断言。
  • 输出「已实现 / todo / na(无实体设备或暂不支持)」三态,na 必须 log 说明原因,不可静默跳过。

11. 端到端工作流

  1. gen-must-test-manifest.ts 从 ONES 拉取 → 生成 must-test.manifest.ts
  2. 按 manifest 的 todo 行,在对应 _connect/_control 测试里补断言并打 [P0][ONES:...] 锚点(遵循主提示词「边跑边写」)。
  3. npm run test:must(添加 + ble + wifi 三段);协议切换不可自动化时请用户手动配合。
  4. 结果按锚点回写 ONES plan CQz9YCNX(添加按 case、控制按 step)。
  5. 更新 manifest status,刷新覆盖率。

相关记忆

project-must-test-ones-source · project-maestro-conversion · feedback-test-case-reuse · feedback-manual-navigation