💻

Test Plan Writer

👤 1++ 📦 v1.0.12 ⭐ 4.5 ⬇️ 255 下載
💻 開發程式設計 免費

📖 技能介紹


slug: test-plan-writer name: test-plan-writer version: "1.0.12" changelog: - "1.0.12: 擴充知識庫查詢範圍,增加服務相關查詢維度(測試策略、資料篩選、功能開關、預期差異、業務場景)" - "1.0.11: 修復changelog格式、恢復description欄位" - "1.0.9: 更新test-plan-template.md測試執行方式說明,區分Jenkins MCP與本地執行,移除壓測流水線" - "1.0.8: 同步qa-integration-pipeline取消壓測,required_phases更新為[1,2,3,4,5,6],Phase 6改為彙總報告" - "1.0.7: 明確sourceFiles為source_files.txt索引檔案路徑,更新檢查清單A操作步驟" - "1.0.6: 對照組白名單支援獨立driver_id,完善experiment_config說明" - "1.0.4: 修正changelog、補充experiment_config與分組預期差異" - "1.0.3: 增加 experiment_config 實驗/灰度配置欄位、分組預期差異格式、required_phases 對映更新(Case 生成必須執行,壓測暫不執行)" - "1.0.2: 最佳化欄位存在性檢查、Thrift/Proto區分搜尋、欄位來源約束、待確認標註規範、自檢清單" - "1.0.0: 初始版本,支援標準 test_plan.md 生成" displayName: "Test Plan Writer" description: "基於 PRD 和程式碼變更分析,生成標準化測試方案(test_plan.md)。職責包括:設計測試場景、定義資料篩選條件、評估風險等級、決定所需流水線階段。"


測試方案生成器

角色定位

本 Skill 是方案設計層,專注測試方案生成,不執行具體測試。

職責: 1. 分析 PRD 需求與程式碼變更範圍 2. 設計可觀測協議欄位級別的測試場景 3. 定義資料篩選條件(供下游 search-data 使用) 4. 評估風險等級,決定 required_phases 5. 生成標準化 test_plan.md


輸入引數

引數 必填 說明
feature 功能名,用於目錄命名和方案標識
designDoc map-spec 設計文件路徑(.claude/workflow/<slug>/design.md
sourceFiles map-spec 傳入的 source_files.txt 檔案路徑(.claude/workflow/<slug>/source_files.txt)。內容為純文本,每行一個變更檔案路徑。僅用於輔助瞭解改動範圍,不用於需求分析

執行步驟

⚠️ 前置強制檢查(阻塞項 vs 警告項)

在生成測試方案前,必須完成以下檢查。檢查項分為兩類:

型別 含義 未通過處理
🔴 阻塞項 必須修復,禁止繼續 返回對應步驟修正
🟡 警告項 允許標註後通過,但需在輸出中顯性標註 記錄到自檢清單

檢查清單 A:程式碼 diff 分析(🟡 警告項)

檢查項 操作 通過標準 未通過處理
讀取 sourceFiles read_file <sourceFiles> 獲取索引檔案,解析每行得到程式碼檔案路徑列表 索引檔案已讀取且至少包含一個有效路徑 標註 [警告: sourceFiles 為空],繼續
讀取程式碼檔案 對解析出的每個路徑執行 read_file <路徑> 關鍵檔案內容已讀取 標註 [待確認: 需開發確認],繼續
提取日誌關鍵字 grep_code regex="LOG.*<函式名>" path="<程式碼檔案路徑>"(對列表中各檔案分別搜尋) 找到日誌語句 標註 [待確認: 需開發確認],繼續
提取 Apollo Key grep_code regex="GetConfig|apollo" path="<程式碼檔案路徑>"(對列表中各檔案分別搜尋) 找到配置讀取 標註 [待確認: 需開發確認],繼續
確認改動分支 grep_code regex="if.*event_type.*5" path="<程式碼檔案路徑>"(對列表中各檔案分別搜尋) 找到條件分支 標註 [警告: 未找到相關分支],繼續

為什麼不阻塞? sourceFiles 可能為空(map-spec 未傳入),或程式碼變更未提交到 git。允許降級為"待確認"標註,但必須在輸出中顯性記錄。


檢查清單 B:欄位存在性確認(🔴 阻塞項)

檢查項 操作 通過標準 未通過處理
Thrift 搜尋 grep_code regex="<欄位名>" path="src/navi-guide/src/proto/thrift" 找到欄位定義 阻塞:禁止虛構欄位
Proto 搜尋 grep_code regex="<欄位名>" path="src/navi-guide/src/proto/protobuf" 找到欄位定義 阻塞:禁止虛構欄位
建立欄位來源表 記錄欄位所屬訊息和行號 每個欄位都有來源 阻塞:必須補充來源

為什麼阻塞? 虛構協議欄位會導致測試方案完全不可執行,下游 search-data 和 diff 都會失敗。這是底線。


檢查清單 C:預期結果量化檢查(🔴 阻塞項)

檢查項 檢查內容 通過標準 未通過處理
數值量化 包含具體數值或範圍 如"數量 >= 1"而非"有效" 阻塞:返回修正
欄位結構 包含具體的欄位名 如"forkPoint 非空" 阻塞:返回修正
識別方法 內部狀態的識別規則 如"通過 multiRoadsForkPoints 非空識別" 阻塞:返回修正

禁止使用的模糊詞:正常、有效、正確、成功、合理、最佳化、提升、改善、包含有效資訊、解析成功

例外處理:若確實無法量化(如使用者體驗類最佳化),在 說明 中寫明量化困難原因替代驗證方式 → 降為 🟡 警告項,允許通過。


Step 1: 讀取設計文件

  1. 讀取 designDoc
  2. 讀取 map-spec 生成的設計文件
  3. 提取:功能描述生效場景改動點約束條件涉及的協議欄位

  4. 提取測試設計要素

  5. 從 designDoc 中直接提取測試所需資訊,包括:
    • trigger_condition:生效場景、約束條件
    • expected_behavior:功能描述中的預期輸出
    • affected_fields:涉及的協議欄位

Step 2: 提取關鍵資訊

designDoc(map-spec 設計文件)中提取: - 功能描述與生效場景 - 涉及的協議欄位(如 ttsContentvoiceTypeeventType) - 觸發條件(如 scene_type == F_FORK && distance <= 150m) - 功能開關控制: - 開關型別(灰度 / AB實驗 / Apollo配置 / 無) - Apollo Key、預設值 - 若是灰度:白名單內容 - 若是 AB實驗:實驗組/對照組白名單、實驗ID - 若是 Apollo配置:本地配置是否生效 - 約束條件(如"不影響普通十字路口") - 改動點(檔案、函式、插入位置)

可查詢資訊源(AI 在生成方案時可主動查詢):

資訊源 查詢方式 用途
知識庫(LLM-Wiki) 呼叫 http://10.190.56.84:8080/search 語義檢索與 feature / sourceFiles / 欄位名 / 服務相關關鍵詞 瞭解同類功能的歷史測試方案、已知問題、協議欄位含義、邊界條件、服務部署配置、測試策略決策、資料篩選經驗、diff 分析規則、迴歸測試經驗
歷史用例 檢索 src/navi_guide_tools/case/ 下同類功能的測試用例 複用或參考歷史場景的 trigger_condition、資料篩選條件
協議定義 讀取 src/navi-guide/src/proto/ 下的 .thrift / .proto 檔案 提取協議中實際存在的欄位名、欄位型別、巢狀結構,作為黑盒測試的唯一輸入輸出依據
Apollo 配置 檢索相關配置項或白名單定義 確認開關型別、白名單內容、AB 實驗分組規則
程式碼變更 讀取 sourceFiles 中的具體程式碼 diff 確認改動點、新增欄位、條件分支邏輯

designDoc 是主要資訊來源,已包含足夠的需求描述和變更範圍。當 designDoc 資訊不足以準確描述預期輸入輸出(如欄位取值範圍、協議格式、歷史相容性約束)時,必須主動查詢上述資訊源補充,確保測試方案准確。

黑盒測試約束:本 Skill 生成的測試方案用於黑盒測試,所有 trigger_condition(輸入條件)和 expected_behavior(預期輸出)中的欄位必須是協議中實際存在的欄位。禁止構造協議中不存在的欄位或假設未定義的巢狀結構。若對欄位存在性有疑問,必須查詢協議定義檔案確認

Step 2.5: 欄位存在性確認(阻塞項)

在生成任何測試場景之前,必須完成以下確認:

1. 欄位存在性確認順序(知識庫 → Proto 真相源)

採用兩級確認機制,平衡效率與準確性:

Step 1: 查詢 LLM-Wiki 知識庫(快速索引)
    └─ 欄位在檢索結果中?→ 是 → 直接使用,跳過 proto 搜尋
    └─ 欄位不在檢索結果中?→ 否 → 進入 Step 2

Step 2: 搜尋 Proto 檔案(唯一真相源)
    └─ 欄位在 proto 中?→ 是 → 新欄位,記錄並標註 [新增欄位: 待 LLM-Wiki 同步]
    └─ 欄位不在 proto 中?→ 否 → 進入 Step 3

Step 3: 程式碼 diff 輔助校驗
    └─ 在 diff 中找到?→ 是 → 可能是內部變數,禁止用於測試
    └─ 在 diff 中也找不到?→ 否 → 標註 [待確認: 需開發確認]

LLM-Wiki 知識庫檢索

服務地址:http://10.190.56.84:8080 Collection:navi-guide-qa-knowledge(需預先建立並上傳知識庫文件)

檢索方式:

POST http://10.190.56.84:8080/search
Content-Type: application/json

{
  "collection": "navi-guide-qa-knowledge",
  "query": "<feature 關鍵詞 或 欄位名>",
  "limit": 5
}

檢索時機: - Step 1 欄位存在性確認時,用欄位名作為 query 快速檢索 - 設計測試場景前,用 feature 關鍵詞檢索歷史測試方案和已知問題 - 遇到邊界條件不確定時,檢索相關規則和經驗 - 確定測試策略時:檢索同類功能的 required_phases 決策依據、風險等級評估標準 - 定義資料篩選條件時:檢索歷史篩選方案(diff / script / reuse)的選擇依據和 filter_config 模板 - 配置功能開關時:檢索歷史 Apollo Key 命名規範、灰度開關配置模式、AB 實驗分組規則 - 定義預期差異時:檢索歷史 diff 預期差異定義格式、unexpected_diff 判定規則 - 設計業務場景時:檢索業務規則、播報邏輯、輪次定義、場景觸發條件等業務知識(如"播報輪次"、"路口型別"、"距離閾值"等)

檢索結果中的 headingtext 可用於拼接 RAG 上下文,輔助測試方案設計。 LLM-Wiki 檢索結果不能作為欄位存在性的最終依據,最終確認仍需搜尋 proto 檔案。

協議檔案(唯一真相源)

導航服務採用 Thrift 定義介面 + Protobuf 定義響應資料結構,需區分搜尋:

欄位型別 協議檔案 搜尋目標
請求欄位(如 event_typeroute_type .thrift 檔案 navi_guide_service.thrift 中的 NaviGuideRequest
響應欄位(如 eventTypeforkPoint .proto 檔案 RouteGuidanceInfoRouteGuidanceInfos 等訊息

唯一搜索範圍src/navi-guide/src/proto/

該目錄下包含所有 Thrift 介面定義和 Protobuf 資料結構定義,不侷限於 navi_guide_service.thriftnavi_guide_service_apply.proto

  • Thriftsrc/navi-guide/src/proto/thrift/*.thrift(13 個檔案,含介面、請求/響應結構體)
  • Protosrc/navi-guide/src/proto/protobuf/*.proto(8 個檔案,含響應資料結構、路線特徵、放大圖等)

其他路徑(如 src/ng_diff_new/src/navi_guide_tools/ 下的 proto)不得作為欄位存在性確認的依據

搜尋策略: - 先用 grep_codesrc/navi-guide/src/proto/全域性搜尋欄位名 - 若命中,讀取具體檔案確認欄位所屬訊息和型別 - 若未命中,再用 search_file 掃描專案內其他 .thrift / .proto 作為兜底

2. 區分請求訊息與響應訊息

導航服務的協議結構特點: - 響應訊息:通常為 RouteGuidanceInfo(單路徑誘導資訊)或 RouteGuidanceInfos(多路徑誘導資訊),包含 forkPointmultiRoadsForkPointseventTypettsContent 等欄位 - 請求欄位:請求引數(如 event_type)通常不在單獨的 "Request" 訊息中定義,而是通過以下方式確認: - 響應中 eventType 欄位的註釋為"請求時的event_type",說明它是從請求透傳的引數 - 查閱 designDoc 中的請求引數說明 - 查閱歷史用例中的請求構造程式碼

3. 搜尋欄位的具體操作

對候選欄位執行以下驗證,根據欄位型別選擇搜尋目標

A. 請求欄位(trigger_condition 中使用)→ 搜尋 Thrift:

# 操作 1:在 thrift 目錄下全域性搜尋欄位名(精確匹配,區分大小寫)
grep_code regex="欄位名\s*:" path="src/navi-guide/src/proto/thrift"

# 操作 2:檢視命中的檔案,確認欄位所屬結構體
grep_code regex="struct\s+\w+\s*\{" path="<命中檔案>" -A 100

B. 響應欄位(expected_behavior / affected_fields 中使用)→ 搜尋 Proto:

# 操作 1:在 proto 目錄下全域性搜尋欄位名(精確匹配,區分大小寫)
grep_code regex="欄位名\s*=" path="src/navi-guide/src/proto/protobuf"

# 操作 2:檢視命中的檔案,確認欄位所屬訊息
grep_code regex="message\s+\w+\s*\{" path="<命中檔案>" -A 200

# 操作 3:若無精確匹配,嘗試模糊搜尋
grep_code regex="欄位名" path="src/navi-guide/src/proto/protobuf" -i

4. 建立欄位來源表

每確認一個欄位,記錄到來源表:

欄位名 來源(請求/響應) proto 中的訊息 確認方式
eventType 響應(請求透傳) RouteGuidanceInfo 精確匹配
multiRoadsForkPoints 響應 RouteGuidanceInfo 精確匹配

5. 程式碼 diff 輔助校驗(解決欄位名/關鍵字精確性)

此步驟利用程式碼變更內容輔助校驗 designDoc 中提到的欄位名、日誌關鍵字、Apollo Key 是否與程式碼實現一致。不是需求融合,僅為命名精確性校驗。

當 designDoc 中提到的以下資訊需要精確確認時,讀取程式碼 diff 輔助驗證:

獲取 diff 的方式(按優先順序): 1. sourceFiles 引數中的變更檔案列表 → 直接讀取這些檔案的關鍵程式碼段 2. 執行 git diff HEAD → 獲取完整程式碼變更 3. 檢查 workflowDir/diff-report.md → map-spec code-review 階段已生成的 diff 報告

diff 輔助校驗的應用場景

場景 操作 示例
designDoc 寫 event_type,不確定 proto 中是 event_type 還是 eventType 在 diff 中搜索 event_typeeventType,看程式碼中實際使用的欄位名 diff 中出現 eventType = request->event_type → 確認 proto 中是 eventType
designDoc 提到"日誌列印 SetmultiRoadsForkPoints" 在 diff 中搜索 LOGprintf 語句,確認日誌關鍵字 exact match diff 中出現 LOG(INFO) << "SetmultiRoadsForkPoints event_type=" → 確認關鍵字
designDoc 提到"灰度開關 fix_eventtype5" 在 diff 中搜索 apolloGetConfig,確認 Apollo Key 完整名稱 diff 中出現 GetConfig("fix_eventtype5_parseforkpoint_gray_switch") → 確認 Key
designDoc 提到新增欄位 fork_points 在 diff 中搜索 fork_points,若程式碼中只有 forkPointmultiRoadsForkPoints → 禁止虛構 fork_points

校驗規則: - 若 designDoc 中的欄位名/關鍵字與 diff 中的程式碼實現不一致,以程式碼實現為準 - 若 designDoc 中未提及但 diff 中發現新增欄位/開關,在測試方案中標註為新增,並納入欄位來源表 - 若 diff 中也找不到對應欄位,標註 [待確認: 需開發確認]

6. 欄位不在現有來源表中的處理(新欄位發現流程)

若搜尋到的欄位不在當前欄位來源表中,說明可能是新引入的欄位,執行:

  1. 確認是否為本次需求新增欄位
  2. 結合 sourceFiles 和 diff 內容,確認該欄位是否在本次變更中新增
  3. 若是新增欄位 → 進入新欄位確認流程
  4. 若是已有欄位但來源表遺漏 → 補充到來源表

  5. 新欄位確認流程Step A: 在 .proto 中定位欄位所屬訊息(請求/響應) Step B: 確認欄位型別(optional/required/repeated) Step C: 記錄到欄位來源表 Step D: 同步到 LLM-Wiki(見下方「新欄位知識庫同步」)

新欄位知識庫同步

當 Step 2 發現新欄位時,直接通過 /index 同步到 LLM-Wiki:

POST http://10.190.56.84:8080/index
Content-Type: application/json

{
  "collection": "navi-guide-qa-knowledge",
  "docs": [
    {
      "id": "new-field-<feature>-<field_name>",
      "text": "欄位: <field_name>\n型別: <type>\n所屬訊息: <Message>\n來源: <proto/thrift>\n說明: <簡要說明>\n引入功能: <feature>"
    }
  ]
}

如批次發現多個新欄位,合併為一個 docs 陣列一次性 /index 注入。

  1. 臨時處理:若來不及同步 LLM-Wiki,在欄位來源表中標註 [新增欄位: 待 LLM-Wiki 同步],但不影響測試方案生成

7. 標記不確定項:若 PRD 或 designDoc 中提到的概念無法對映到協議欄位(如"版本切換"、"已走過的 link"),禁止直接虛構欄位名,應: - 優先尋找協議中可間接表徵該狀態的欄位 - 若找不到,在 trigger_condition 中使用最相關的真實欄位(如 eventType == 5),並在說明中備註"版本切換狀態通過響應差異反推" - 絕不能使用 C++ 內部變數名(如 route_has_version_switchhas_traveled_links)作為測試依據

8. 欄位命名規範:嚴格使用 proto 檔案中的欄位名(區分大小寫,如 eventType 而非 event_type

Step 3: 設計測試場景

📋 場景細分方法論

規則 1:觸發條件相同的場景處理

當多個場景的 trigger_condition 完全相同(如都是 event_type == 5),必須採用以下方式之一

方式 A:合併場景(統計方式)(推薦)

### S001: event_type=5 場景(合併)

- **觸發條件**: `event_type == 5`
- **預期分佈**:
  - 版本切換場景(約 30%):`multiRoadsForkPoints` 有差異(CHANGED)
  - 無版本切換場景(約 70%):`multiRoadsForkPoints` 無差異(UNCHANGED)
- **識別方法**: 通過響應中 `multiRoadsForkPoints` 非空識別版本切換

方式 B:區分場景(明確識別方法)

### S001: event_type=5 且發生版本切換

- **觸發條件**: `event_type == 5` **且滿足以下之一**:
  - 響應中 `map_version` 與請求不一致
  - 響應中 `multiRoadsForkPoints` 非空(新邏輯生效後)
- **預期行為**: `multiRoadsForkPoints` 包含分歧點(數量 >= 1)

### S002: event_type=5 且無版本切換

- **觸發條件**: `event_type == 5` **且**:
  - 響應中 `map_version` 與請求一致
- **預期行為**: `multiRoadsForkPoints` 與基線一致(UNCHANGED)

強制要求:若採用方式 B,必須給出明確的識別字段或方法,禁止僅標註"通過響應差異反推"而不說明具體方法。

規則 2:灰度開關場景完整覆蓋

若需求提到灰度開關,必須包含以下場景:

場景 觸發條件 預期差異 優先順序
灰度關閉 event_type == 5(灰度開關關閉) UNCHANGED(與基線一致) P0
灰度開啟-生效 event_type == 5(灰度開關開啟,命中白名單) CHANGED(新邏輯生效) P0
灰度開啟-未生效 event_type == 5(灰度開關開啟,未命中白名單) UNCHANGED(走老邏輯) P0

規則 3:邊界場景系統設計

必須覆蓋的邊界維度(根據業務邏輯選擇至少 2 個維度,每個維度至少 2 個邊界點):

維度 邊界點 示例場景
時間/進度邊界 剛觸發、觸發後一段時間、長期 剛版本切換、切換後 10km、切換後到達終點
空間邊界 起點、中途、終點 起點 0km、中途 50%、終點前 100m
數量邊界 0、1、多個 無分歧點、1 個分歧點、多個分歧點
狀態邊界 正常、異常、極限 正常版本切換、切換失敗、多次切換

基於協議中實際存在的可觀測欄位設計測試場景,每個場景必須包含:

欄位 說明 欄位來源限制
scenario_id 唯一標識,如 S001 -
scenario_name 場景名稱,簡明描述測試意圖 -
trigger_condition 觸發條件(協議欄位 + 閾值) 只能使用請求協議中的欄位
expected_behavior 預期行為(具體欄位值變化) 只能使用響應協議中的欄位
affected_fields 受影響的可觀測欄位列表 只能使用響應協議中的欄位
test_type diff / functional / boundary -
驗證方式 協議欄位 / 日誌 / 協議+日誌 若選日誌協議+日誌,日誌關鍵字必須來自原始碼確認
priority P0 / P1 / P2 -

欄位使用規則: - trigger_condition 中的欄位必須是請求訊息(Request)中實際存在的欄位 - expected_behavioraffected_fields 中的欄位必須是響應訊息(Response)中實際存在的欄位 - 禁止將 C++ 內部變數、臨時計算量、未序列化的記憶體物件作為測試依據 - 若需求描述中的概念無法直接對映到協議欄位,應使用最接近的真實欄位,並在場景說明中解釋對映關係

示例場景

### S001: F 路口提前播報
- **觸發條件**: `scene_type == F_FORK && distance_to_fork <= 150m`
- **預期行為**: `ttsContent` 包含 "前方路口",提前 50m 播報
- **受影響欄位**: `ttsContent`, `voiceType`
- **測試型別**: diff
- **優先順序**: P0

Step 4: 定義資料篩選條件

為每個 diff 型別場景定義資料篩選條件:

條件維度 示例
scene_type F_FORK, T_JUNCTION
distance_range 100m ~ 200m
version >= 490
city_list 北京、上海、深圳
time_range 高峰時段覆蓋

篩選條件欄位限制: - 篩選條件只能使用請求協議中實際存在的欄位 - 禁止用響應欄位、C++ 內部變數或 AI 推導的抽象概念作為篩選維度 - 若需求涉及無法直接篩選的內部狀態(如"版本切換"、"已走過的 link"),應: 1. 先用請求中可篩選的欄位縮小範圍(如 eventType == 5) 2. 再通過 diff 輸出的響應差異來識別目標場景 3. 在 說明 列中標註"內部狀態通過響應差異反推,非直接篩選"

生成 data_filter_conditions 欄位,供 search-data-script 使用。

Step 5: 評估風險等級、測試策略與 required_phases

根據以下因素評估:

因素 高風險表現
改動範圍 核心演算法、多模組聯動
影響面 全量使用者、全場景
欄位型別 語音播報、安全相關事件
歷史穩定性 同類改動曾引發線上問題

風險等級與 required_phases 對映

風險等級 說明 required_phases
low 純配置/文案變更,影響面極小 [1, 2, 3, 4]
medium 單一場景最佳化,影響面可控 [1, 2, 3, 4, 5, 6]
high 核心演算法變更,多場景聯動 [1, 2, 3, 4, 5, 6]

Phase 6(彙總報告)為必須執行階段,用於彙總各 Phase 產物生成最終報告。

測試策略建議(寫入 test_plan.md "測試策略"章節):

變更型別 Diff 功能 Case 迴歸 說明
純配置/文案調整 必須 Case 生成驗證配置生效
新功能/新場景 必須
演算法最佳化 必須 diff 覆蓋核心差異,Case 驗證邊界
邏輯修復/Bugfix 必須 Case 驗證邊界場景
介面變更 必須

功能 Case 為必須執行,用於驗證邊界場景和補充 diff 無法覆蓋的功能點。壓測暫不執行。

邏輯修復特殊說明:若修復的是特定場景下的異常處理邏輯(如本例的 event-type=5 版本切換),功能 Case 用於驗證邊界場景(部分走過、全走過),壓測通常不需要。需在"判斷依據"中明確說明為何選擇該策略。

AB 實驗特殊策略: - Diff 需跑兩組:實驗組(基線 vs 實驗組)+ 對照組(基線 vs 對照組) - 實驗組預期:有差異(符合 test_plan 預期) - 對照組預期:無差異(對照組應與基線一致) - 對照組白名單:對照組可能使用獨立白名單(driver_id 非空),也可能與非白名單共用預設邏輯(driver_id=""),視實驗設計而定 - 若對照組出現差異 → 實驗分流邏輯有問題,需標記為 bug

Step 6: 生成 test_plan.md

輸出路徑:<CASE_DIR>/<feature>/test_plan.md

test-plan-template-v2.md 模板格式生成,確保包含以下必填欄位: - feature:功能名 - 測試執行方式:列出 Jenkins MCP 排程的流水線(diff 流水線 / 迴歸流水線 / 壓測流水線),標註是否使用 - test_scenarios:測試場景列表(每個場景含 scenario_id / trigger_condition / expected_behavior / affected_fields / test_type / 驗證方式 / priority) - 驗證方式協議欄位(僅 diff 驗證) / 日誌(僅日誌驗證) / 協議+日誌(兩者結合) - data_filter_conditions:資料篩選條件(供 search-data 使用) - 功能開關控制:開關型別、白名單、實驗組等資訊 - 測試策略:Diff / 功能 Case / 迴歸 / 壓測 的是否需要執行 - experiment_config:實驗/灰度配置(決定 diff 執行次數和分組) json { "type": "ab_test", "groups": [ {"name": "control", "driver_id": "202606101119", "desc": "對照組(白名單A)"}, {"name": "treatment", "driver_id": "580548822047701", "desc": "實驗組(白名單B)"} ] } - typenone(無實驗)/ ab_test / grayscale - groups:diff 分組列表,每組含 namedriver_iddesc - driver_id:該組的白名單 ID。空字串表示非白名單(走預設邏輯),非空字串表示使用該白名單 - 對照組可能有自己的白名單(如對照組白名單A),也可能不設白名單(空字串,與非白名單共用預設邏輯) - 由功能開關控制資訊自動推導:若開關型別為 AB實驗/灰度,則 type 對應設定,groups 按對照組/實驗組或白名單/非白名單拆分 - diff_config:Diff 執行配置與預期結果(輸入不可預期,但輸出必須可預期) - 對比配置:基線/目標服務地址(對比欄位、忽略欄位、請求資料來源等由 ng_diff_new 內部實現決定,測試方案僅指定 host) - 預期差異結果(Expected Diff):每個場景下哪些欄位、基線值→目標值、變化方向(CHANGED/ADDED/REMOVED/UNCHANGED)。注意:diff 輸入為線上真實流量,無法預先控制哪些請求會被打到,上表定義的是"如果某個請求的響應中該欄位出現差異,則差異應符合上述定義" - 分組預期差異:按 experiment_config.groups 中的 name 分組定義預期差異,格式如下: markdown | 分組 | 場景ID | 欄位 | 基線值 | 目標值 | 變化方向 | |------|--------|------|--------|--------|----------| | treatment | S001 | ttsContent | - | 包含"前方路口" | CHANGED | | treatment | S001 | multiRoadsForkPoints | 空 | 數量>=1 | ADDED | | control | S001 | ttsContent | - | - | UNCHANGED | | control | S001 | multiRoadsForkPoints | - | - | UNCHANGED | - 實驗組/白名單組:按正常場景預期填寫(CHANGED / ADDED / REMOVED) - 對照組/非白名單組全部為 UNCHANGED,與基線一致。若對照組出現任何差異 → 實驗分流邏輯有 bug(對照組無論是否有獨立白名單,都應與基線一致) - 非預期差異判定規則:哪些情況屬於 unexpected_diff,供 Phase 2 diff-executor 使用 - 日誌驗證(如適用):哪些場景需結合日誌驗證、日誌關鍵字/指標、預期結果 - required_phases:需要執行的 Phase 列表 - risk_level:風險等級(low/medium/high)

生成過程中的強制校驗: 每生成一個場景,立即執行: 1. 欄位來源校驗trigger_condition 中的欄位是否都在請求 proto 中?expected_behavior / affected_fields 中的欄位是否都在響應 proto 中? 2. 欄位命名校驗:欄位名是否與 proto 中完全一致(區分大小寫)? 3. 任一校驗失敗,禁止繼續生成,必須先修正欄位

待確認項標註規範: 以下資訊若無法從現有文件/程式碼中直接確認,必須標註 [待確認: 需開發確認],禁止虛構:

資訊項 示例 標註方式
Apollo Key fix_eventtype5_parseforkpoint_gray_switch [待確認: 需開發確認] Apollo Key
日誌關鍵字 SetmultiRoadsForkPoints event_type=5 [待確認: 需開發確認] 日誌關鍵字
白名單內容 具體城市/使用者群體 [待確認: 需開發確認] 白名單
欄位存在性 不確定某欄位是否在協議中 必須先查詢 proto 確認,不能標註待確認

日誌關鍵字獲取方式:優先讀取 sourceFiles 中的原始碼,搜尋 LOG / WARN / ERROR / INFO 等日誌輸出語句,提取實際日誌格式。若原始碼不可讀或未找到相關日誌,則標註 [待確認: 需開發確認]

7w4.net小蔥技能站,你的AI助手技能庫。

模板檔案位置:testing/test-plan-writer/test-plan-template.md

Step 7: 自檢與輸出

生成完成後,AI 自檢以下項。以下檢查項為阻塞項,任一項未通過必須修正後方可輸出:

  • [ ] feature 欄位與目錄名一致
  • [ ] test_scenarios 非空,每個場景有完整欄位
  • [ ] data_filter_conditionstest_scenarios 一一對應
  • [ ] data_filter_conditions 中的欄位均為請求協議中實際存在的欄位(無 C++ 內部變數)
  • [ ] 功能開關控制 完整(開關型別、白名單/實驗組資訊)
  • [ ] 測試策略 已根據變更型別自動判斷(Diff / 功能 Case / 迴歸 / 壓測),且判斷依據明確
  • [ ] required_phases 與測試策略一致
  • [ ] risk_level 評估有依據
  • [ ] Diff 預期結果完整性diff_config 中每個 diff 型別場景都有對應的預期差異定義(含場景ID、欄位、基線值、目標值、變化方向)
  • [ ] AB 實驗對照組預期:若為 AB 實驗,對照組的預期差異明確為 UNCHANGED(與基線一致)
  • [ ] 程式碼 diff 分析(阻塞項):若 sourceFiles 非空或 git diff HEAD 可執行,已從 diff 中提取實際日誌關鍵字和 Apollo Key;禁止在已執行 diff 分析的情況下仍標註 [待確認: 需開發確認]
  • [ ] 預期結果量化(阻塞項):每個 expected_behavior 包含具體數值、狀態或範圍;無"正常"、"有效"、"正確"等模糊描述;若無法量化,說明中已寫明量化困難原因和替代驗證方式
  • [ ] 內部狀態識別(阻塞項):designDoc 中提到的內部狀態(如"版本切換"、"已走過的 link")已通過識別方法或場景合併處理;trigger_condition 中無無法從請求欄位推斷的內部狀態
  • [ ] 協議欄位存在性(阻塞項)trigger_condition 中的欄位均在請求協議中存在;expected_behavior / affected_fields 中的欄位均在響應協議中存在;無虛構欄位;欄位名大小寫與 proto 一致
  • [ ] 日誌關鍵字來源:若使用了日誌驗證,日誌關鍵字已標註 [待確認: 需開發確認] 或已讀取原始碼/diff 確認
  • [ ] Apollo Key 來源:若提到了灰度開關/AB實驗,Apollo Key 已標註 [待確認: 需開發確認] 或已從 diff 中提取實際值
  • [ ] 新欄位知識庫同步:若使用了本次需求新增的欄位,已通過 /index 同步到 LLM-Wiki navi-guide-qa-knowledge(或已標註 [新增欄位: 待 LLM-Wiki 同步]

自檢失敗處理流程: 1. 標記失敗的檢查項 2. 返回對應 Step 修正(欄位問題 → Step 2.5/Step 3,日誌問題 → 讀取原始碼或標註待確認) 3. 重新執行自檢,直至全部通過

執行日誌(必須包含在輸出中,便於審計):

## 執行日誌

### 檢查清單 A:程式碼 diff 分析
- [✅/❌/⚠️] 讀取 sourceFiles:`ng_crossfinder_strategy.cpp`
- [✅/❌/⚠️] 搜尋日誌關鍵字:找到 `LOG(INFO) << "SetmultiRoadsForkPoints event_type="`
- [✅/❌/⚠️] 搜尋 Apollo Key:找到 `GetConfig("fix_eventtype5_parseforkpoint_gray_switch")`
- [✅/❌/⚠️] 搜尋分支邏輯:找到 `if (event_type == 5)`

### 檢查清單 B:欄位存在性確認
- [✅] Thrift 搜尋 `event_type`:找到 `NaviGuideRequest` line 332
- [✅] Proto 搜尋 `eventType`:找到 `RouteGuidanceInfo` line 1617
- [✅] Proto 搜尋 `multiRoadsForkPoints`:找到 `RouteGuidanceInfo` line 1610
- [✅] 建立欄位來源表:已完成(4 個欄位全部確認)

### 檢查清單 C:預期結果量化
- [✅] S001 expected_behavior:`multiRoadsForkPoints.size() >= 1`(已量化)
- [✅] S002 expected_behavior:`eventType == 5`(已量化)
- [⚠️] S003 expected_behavior:`與基線一致`(降級為警告,原因:迴歸場景無具體數值可量化)

### 場景細分檢查
- [✅] 觸發條件相同處理:S001-S005 的 trigger_condition 均為 `event_type == 5`,已合併為統計方式
- [✅] 灰度開關覆蓋:已覆蓋關閉/開啟生效/開啟未生效 3 個場景
- [✅] 邊界維度:覆蓋數量邊界(0/1/多個)和空間邊界(起點/中途/終點)

### 質量門禁
- [✅] 待確認項數量:2 項(白名單內容、日誌關鍵字精確格式)
- [✅] 模糊描述檢查:無模糊詞
- [✅] 欄位存在性:無虛構欄位

作用:便於使用者檢查 AI 是否真的執行了關鍵步驟,便於事後審計和改進。

輸出摘要(告知使用者,無需確認):

測試方案已生成:

【功能概述】<簡述>
【測試場景】共 X 個場景(P0: a個, P1: b個, P2: c個)
【功能開關】<開關型別> / <Apollo Key>
【測試策略】(已自動判斷)
  - Diff 對比: 是/否
  - 功能 Case: **必須執行**
  - 迴歸測試: 是/否
【風險等級】<low/medium/high>
【執行階段】required_phases = [...]

任一自檢失敗,重新生成並標註修正點。


輸出校驗

生成完成後,自檢以下項:

  • [ ] feature 欄位與目錄名一致
  • [ ] test_scenarios 非空,每個場景有完整欄位
  • [ ] data_filter_conditionstest_scenarios 一一對應
  • [ ] data_filter_conditions 中的篩選欄位均為請求協議中實際存在的欄位
  • [ ] required_phases 包含 Phase 1(自身)
  • [ ] risk_level 評估有依據(引用改動範圍或影響面)
  • [ ] 篩選對映表 中每條預期差異都有場景對應
  • [ ] trigger_condition 欄位均為請求協議欄位,expected_behavior / affected_fields 欄位均為響應協議欄位
  • [ ] 無虛構欄位,欄位名大小寫與 proto 一致
  • [ ] 日誌關鍵字和 Apollo Key 已確認或已標註 [待確認: 需開發確認]

校驗失敗處理: 1. 標註具體失敗項和原因 2. 返回對應 Step 修正 3. 重新校驗直至全部通過


產出清單

產物 路徑
測試方案 <CASE_DIR>/<feature>/test_plan.md

🤖 AI 評測

這個 Skill 質量很好,文件詳細、邏輯清晰、使用方便。做得好的地方:步驟流程完整、檢查清單詳細、有現成的模板和示例;做了很多質量把關措施,能避免常見錯誤。不足之處:依賴內部服務地址、不方便在外部使用;有些細節說明分散在多處,查詢不夠方便。總體來說,這是一個專業度高、實用性強的 Skill。

📊 多維度評分

適應性4.3
規範性4.4
有效性4.7
可靠性4.4
可信度5

📁 包含檔案 (3 個)

📄 SKILL.md 35.7 KB
📄 test-plan-demo.md 8.3 KB
📄 test-plan-template.md 10.5 KB