# 08 UAT 與驗證

主要讀者：QA、平台維護者、需求驗收負責人。

```mermaid
flowchart LR
  A[固定案例、資料與環境] --> B[受控觸發並記錄 Run]
  B --> C[比對 Step 與 Case 結果]
  C --> D[核對報告、環境及新舊 Run]
  D --> E{符合驗收要求？}
  E -->|是| F[保存證據與簽核]
  E -->|否| G[記錄實作缺口並追查]
```

## 1 驗收原則

驗收對象是測試平台本身，不是某個受測系統的倉儲、履約或製造流程。使用固定回應的測試 API 與可重置的測試資料，先驗證「操作、比對、紀錄、報告」能正確連起來，再驗證排程及環境使用規則。

表中的 Then 是驗收標準，不代表已通過。程式現況與需求不同時，應記錄缺口；不能因舊程式照原邏輯執行，就把需求判為完成。

## 2 關鍵 UAT 矩陣

| ID | 目的 | Given（前置條件） | When（操作） | Then（預期結果） | 現況與驗證重點 |
| :--- | :--- | :--- | :--- | :--- | :--- |
| UAT-01 | 案例準備與選案完整 | 已準備固定資料、同專案 Suite 與一般 Case；含六種步驟設定及共用 hooks | 維護者儲存案例、重新查詢、選入 Plan，再檢視實際執行清單 | 步驟型別與設定完整保存，順序正確；只執行選中一般案及相關 hooks；相依設定不偷偷新增選案 | 已有管理與執行能力；原資料庫案例未取得，不把示例稱為歷史成果；先用靜態設定檢查，再做受控執行 |
| UAT-02 | HTTP 比對與狀態區分 | 測試 API 可切換正確 JSON、內容不符、狀態碼不符及連線例外；每案至少有一項啟用檢查 | 對各情境建立新 Run，查詢 Case／Step 及單次報告 | 正確回應通過；內容或狀態不符為失敗；執行例外保留錯誤。Run 完成不等於全過，報告不得混入別次 Run；零案例／零步驟不得誤稱全部通過 | 程式可將 Case ERROR 留在 FINISHED 的 Run；目前零案例通過率回 100%，零步驟可能 PASSED，屬待補強項 |
| UAT-03 | 初始化失敗與相依範圍 | 必要初始化資料設定完整；另備單表初始化失敗、無 `dataSources` 及前置案例歷史失敗／本次通過的情境 | 注入初始化失敗；再分別執行前置 FAILED、ERROR、未執行及跨次結果情境 | 必要初始化失敗中止本次業務步驟並保存原因；相依僅依本次 Run 判斷，未通過者後續案跳過，不受影響案例可繼續 | 初始化內層有只寫 log 的路徑；無設定直接略過。相依查詢未限 Run、只認 FAILED，因此不能宣告現況符合 |
| UAT-04 | 共用環境排程與人工重跑 | 同一實際環境有兩個 Trigger，另有即時執行要求；保留原 Run；準備維護者與一般開發者身分 | 同時到期；由兩種身分要求重跑整個 Plan；模擬停機錯過排程 | 同環境工作等待、不重疊初始化；維護者才可重跑，建立新 Run、原結果保留、原排程不改；錯過排程由維護者決定是否補跑 | 現況 Trigger 級 cache 碰撞直接返回，即時路徑不同，不能當成環境佇列；授權及錯過排程政策仍待驗證 |
| UAT-05 | 固定關閉與早晨可追查 | 早晚共用同一套 EKS 環境與資料；已設定固定關閉時間、資源範圍及關閉後仍可讀的線索儲存；已核定全量 Plan 清單 | 分別模擬正常完成、初始化失敗、中斷、卡住及報告上傳延遲；到固定時間關閉，早晨重新啟用 | 正常完成自動關閉；其餘情境也不超過固定關閉時間，寄信／上傳不得阻擋。早晨可用原 Run、最後 Case／Step、錯誤及關閉事件追查；若 Run 仍為 RUNNING，能判定需核對且不誤稱全過；維護者確認後才決定重跑 | 固定強制關閉及保留線索是已確認政策；確切時間、全量映射、持久儲存與部署控制仍未驗證，不保證所有強制關閉都來得及寫 INTERRUPTED |

### 2-1 關閉線索的驗收要求

線索必須在強制關閉後仍存在，不得只保存在會消失的執行環境本機。至少需定位原 Run、最後已保存的 Case／Step、發生時間、已知錯誤及關閉事件；詳細內容可以依實際執行狀態不同，但必須足以支持早晨初判。驗收要實際經過「強制關閉 → 早晨啟用 → 查原 Run」，並測試最後一次狀態更新或報告上傳未完成的情境。這是目標驗收要求，持久儲存實作尚未驗證。

### 2-2 證據清單

| 證據 | 必須保存的內容 |
| :--- | :--- |
| 定義與資料 | Plan 選案、Suite／Case／Step 順序及設定、測試資料基準與適用環境 |
| 執行 | `triggerNum`、`runNum`、`runSuiteNum`、`runCaseNum`、`runStepNum` 及開始／結束時間 |
| 比對 | 預期、實際、Step 狀態、斷言回應及錯誤；認證資訊先遮罩 |
| 報告 | 單次 Run 的案例分母、通過／失敗／錯誤／相依跳過數量與收件角色；不要只保存百分比 |
| 環境 | 實際啟用／關閉資源、固定截止時間與實際關閉時間、全量完成條件、關閉後及早晨可讀到的最後進度；未知設定標記待確認 |
| 結論 | 執行時間、執行者、環境、預期與實際差異、通過／失敗或待確認，以及缺陷編號 |

## 3 可重現檢查與既有測試

### 3-1 執行前置條件

| 項目 | 要求 |
| :--- | :--- |
| 建置工具 | 使用專案核定的 JDK／Gradle 與私有套件設定；先確認 Wrapper 與建置 DSL 相容性 |
| 定義檢查 | 可先執行純物件驗證測試，不需啟動 EKS 或呼叫受測系統 |
| 整合測試 | 明確指定可重置資料範圍；同仁使用及其他測試不能與初始化重疊 |
| 初始化 | 核對資料來源、初始化表及排除表。初始化包含清空與回填，不能直接在未知環境試跑 |
| HTTP／方法呼叫 | 使用已核定測試替身或測試服務；既有測試可能連外，不直接整批執行 |
| 通知 | 測試收件群組明確指定；不以實際收件成功替代平台結果驗證 |

### 3-2 既有測試對照

| 測試名稱 | 可核對內容 | 限制 |
| :--- | :--- | :--- |
| `QaC004CheckTest` | HTTP、資料比對等步驟設定的物件檢核 | 不代表整段執行、權限或環境安全已驗證 |
| `RunContextTest` | 變數作用域、數值及 JSONPath 取值 | 部分預期值仍需獨立核對；應指定單一測試，不假設全組都可通過 |
| `HttpStepHandlerTest` | HTTP 步驟執行入口 | 既有內容可能呼叫遠端系統及方法；未改為受控替身前不直接執行 |
| `SqlCompareStepHandlerTest`／`SqlCompareStepHandlerV2Test` | SQL 比對能力 | 依賴資料來源及基準，不能當成無副作用測試 |
| `QaC003ControllerMvcTest` | Suite 管理介面測試參考 | 位於 SIT 測試組；建置中的 SIT 設定有註解，需先確認任務可用 |

下列是優先可重現的建置及純設定檢查命令。命令成功仍須確認有實際發現並執行測試，不能將零測試視為通過。

```bash
./gradlew --version
./gradlew :crystal:test --tests '*QaC004CheckTest*'
```

Crystal 使用 JUnit Platform。標準報告位置為 `crystal/build/test-results/test/` 與 `crystal/build/reports/tests/test/index.html`；若建置先失敗或沒有執行測試，不得引用舊報告當成此次成果。

Sentry 的單一變數測試可在確認 JUnit Jupiter 已被建置發現後執行；此命令不涵蓋會發出遠端請求的 HTTP 測試：

```bash
./gradlew :sentry:test --tests '*RunContextTest.string_variable'
```

對應標準報告位置為 `sentry/build/test-results/test/` 與 `sentry/build/reports/tests/test/index.html`。完整平台 UAT 仍需依上表在受控環境執行；不能由這些小範圍測試取代。

## 4 驗證紀錄與未驗證項目

| 檢查 | 狀態 | 說明 |
| :--- | :--- | :--- |
| 九份核心文件及閱讀版連結 | 通過 | 文件齊全，站內檔案與章節連結可定位；見[文件檢查紀錄](pages/verification.json) |
| 六張 BPMN | 通過 | 嚴格檢查零警告，模型為分析用途，黑白預覽齊全；見[BPMN 檢查紀錄](bpmn/validation.txt) |
| 九張 Mermaid | 通過 | 已解析並產生閱讀版圖面；見[圖面檢查紀錄](pages/mermaid-validation.json) |
| 業務 BDD 情境（英文關鍵字、中文敘述） | 通過語法與結構檢查 | 5 份 feature、37 個情境、47 個展開例子（不含環境啟停與隔日追查等維運事項）；尚未接上 step definitions，未執行業務測試；見[BDD 指南](biz-bdd/README.md)與[檢查紀錄](biz-bdd/validation.json) |
| HTML 閱讀版與圖片操作 | 通過 | 離線檢查 16 頁的桌面／手機版，共 32 次頁面及 30 次圖片操作；縮放、符合視窗、原始大小、關閉、鍵盤與焦點返回均通過；見[閱讀版檢查紀錄](pages/visual-validation.json) |
| OpenAPI HTML 閱讀介面 | 通過 | Swagger UI 離線呈現 72 個操作與 114 個 schema；桌面／手機版篩選、參數、請求／回應及模型展開檢查通過，內嵌合約與 YAML 相同，沒有對外請求；見[閱讀介面檢查](pages/openapi-validation.json) |
| OpenAPI 與實際介面宣告 | 通過靜態比對 | 64 個路徑、72 個操作、114 個 schema；已比對目前介面的方法、路徑、參數及請求內容宣告；見[API 檢查紀錄](pages/api-validation.json) |
| 資料字典與物件欄位 | 通過靜態比對 | 17 張表的 186 個映射欄位、76 個輔助欄位，以及 20 個步驟 JSON 模型的 75 個欄位，合計 337 個欄位；已檢查欄位覆蓋與中文說明。部署中的資料表限制尚未驗證 |
| UAT-01～05 | 尚未執行 | 沒有本次測試 Run、實際回應、環境啟停及通知證據 |
| Java 測試 | 尚未執行 | 未連線初始化資料、未呼叫受測系統、未發送 Email |
| EKS 日夜啟停 | 使用者已確認運作與固定強制關閉政策，實作未驗證 | 確切截止時間、啟停資源、全量 Plan 對應及關閉後線索持久保存仍需驗證 |
| 90 天保留與清理 | 已確認需求，未驗證實作 | 須核對清理範圍、執行結束起算及邊界資料；不直接清除現有紀錄 |
| 重跑權限、同環境排隊、相依與初始化保護 | 已確認需求，仍有差異 | 以 UAT-03／04 驗收，不以 enum 或 API 存在推論符合 |

以上通過項目只證明文件結構、圖面及程式宣告的靜態一致性，不代表平台 UAT 已通過。

### 4-1 重新產生與檢查閱讀版

在專案根目錄執行下列命令。`SA_TOOL_MODULES` 指向含有 `marked`、`mermaid`、`puppeteer` 的既有 Node.js 套件目錄；`BDD_TOOL_MODULES` 指向含有 `@cucumber/gherkin`、`@cucumber/messages` 與 `yaml` 的目錄。Python 環境需安裝 `PyYAML` 與 `openapi-spec-validator`。依賴版本與操作方式見[閱讀版維護說明](pages/README.md)。

```bash
SA_TOOL_MODULES=/path/to/render/node_modules BDD_TOOL_MODULES=/path/to/bdd/node_modules node sa_specs/pages/build.mjs
python3 sa_specs/pages/verify.py
```

一般文件檢查會核對檔案、連結、OpenAPI、BPMN 及 Mermaid 數量。重新比對程式欄位需另提供由當前程式產生的資料字典與步驟模型清單，並安裝 `javalang`；不帶清單的命令不會重新執行欄位覆蓋檢查。BPMN 重建方式見[模型說明](bpmn/README.md)。

故障診斷與復原驗證見[排障手冊](07_TROUBLESHOOTING_RUNBOOK.md)。
