Test Plan: Spec 2 階段抽象整合

產出日期:2026-05-12 對應 specdesign.md v2、../README.md 對應 planimplementation-plan.md v1 跨 repo:compliance-manager-be / compliance-manager-fe / compliance-manager-test


1. Acceptance Criteria 對應

從 design.md §二 需求摘要 7 條 + §九 6 條決議萃取,作為測試覆蓋依據。

AC ID 條件 來源
AC-1 AP 建立時同步寫 compliance.assessment_plan_extensions 列(含 workflow_execution_uid + flow_template_snapshot_uid),1:1 強制 design §9.1, plan §B.5
AC-2 AP 建立完成後 BPMN main workflow 啟動且停在 planning UserTask;AP.status 維持 preparing design §9.5, plan §B.5
AC-3 GET .../stage/info 回傳當前 stage code / name / progress / precondition / user_can_advance design §四, plan §B.3
AC-4 Progress bar 解析 BPMN snapshot 取出 4 stage 序列;已完成標 done、當前標 current、未到標 pending design §四
AC-5 POST .../stage/advance 依 stage handler key 呼叫對應 OSCAL API(activate / launch_audit / confirm_audit / close_round) design §9.3, plan §B.1
AC-6 planning 推進 → AP preparing→active;task_execution → active→auditing;audit → auditing→remediation(或 closed if no poam);poam → remediation→closed design §二 §9.5, GRC §2.1
AC-7 推進前驗證使用者擁有 stage default_main_roles(或 BPMN UserTask 覆寫的 main_roles);不足 → 403 GRC_STAGE_ROLE_FORBIDDEN design §9.7, plan §B.3
AC-8 推進前跑 precondition.check();fail 且非 force → 412 GRC_STAGE_PRECONDITION_FAILED 含 reason_i18n_key + context design §9.2 §9.7
AC-9 manager 可帶 force=true bypass precondition;非 manager 不可 design §9.2
AC-10 task_execution precondition = TasksThresholdCheck(incomplete > 0 時 fail) design §9.3 stage map
AC-11 audit precondition = AllControlsVerdictedWithFinding(未判定或 fail/partial 無 finding → 412) design §9.3, GRC GRC_412003/GRC_412011
AC-12 poam precondition = AllPoamClosed(仍有 open POA&M → 412) design §9.3, GRC GRC_412005
AC-13 AP 未綁 workflow_execution → 404 GRC_AP_NO_WORKFLOW_BINDING design §9.7
AC-14 BPMN 已到 EndEvent / 找不到下一節點 → 400 GRC_STAGE_NO_NEXT_NODE design §9.7
AC-15 Stage handler key 未在 Registry 註冊 → 400 GRC_STAGE_HANDLER_NOT_REGISTERED design §9.7
AC-16 BPMN UserTask 未綁定 stage object → 400 GRC_STAGE_OBJECT_NOT_BOUND design §9.7
AC-17 EndEvent 觸發時不重複改 AP.status(close_round handler 為 single source of truth);移除 raw SQL ExtAssessmentPlanRepoImpl design §9.4, plan §B.6
AC-18 poam on_complete v1 直接走 close_round 結案;loop back 路徑 BPMN 圖可見但 runtime 不走 design §9.4
AC-19 Spec 2 使用 hardcode builtin-full-audit 範本;flow_template_snapshot_uid 欄位預留供 Spec 3 user 選範本 design §9.6, plan §B.5
AC-20 FE FlowPhaseBanner 渲染 stage name / progress / hint / 推進按鈕;precondition fail → 按鈕 disable + tooltip;manager 可 ConfirmDialog force design §四 §9.2
AC-21 FE 4 個 routed view(settings / overview / audit / poam)掛 Banner;既有 4 個推進按鈕拆除;4 個導航按鈕不動 design §三, plan §D.1~D.4
AC-22 task_execution stage Banner 掛在 overview 頁;待辦任務頁不掛 Banner design §四, plan §D.5
AC-23 flow_engine 模組不 import grc / oscal;handler 透過 DI container 註冊到 Registry(架構約束) design §9.3

2. BE 測試(pytest,compliance-manager-be/test/

2.1 Repository / Mapper 層

Test File Test Method 驗證對象 覆蓋 AC
test_assessment_plan_extension_repo.py test_get_by_ap_id_returns_entity 既有列可查 AC-1
同上 test_get_by_ap_id_not_found_returns_none 無對應列回 None AC-1
同上 test_get_by_ap_uid_via_join 透過 AP uid join 查到 ext AC-1
同上 test_add_extension_persists_workflow_uid INSERT 後 workflow_execution_uid 寫入 AC-1
同上 test_set_workflow_execution_uid_updates_audit_fields updated_user / updated_at 自動更新 AC-1
同上 test_unique_constraint_blocks_duplicate_ap_id 同 ap_id INSERT 二次拋 IntegrityError AC-1
同上 test_cascade_delete_when_ap_deleted AP delete 時 ext 跟著刪 AC-1
test_assessment_plan_extension_mapper.py test_entity_to_model_roundtrip Mapper 雙向轉換無 lossy AC-1

2.2 Domain Registry / Interface 層

Test File Test Method 驗證對象 覆蓋 AC
test_stage_completion_registry.py test_register_handler_then_get_returns_same_instance register / get_handler AC-23
同上 test_register_precondition_then_get register / get_precondition AC-23
同上 test_get_handler_missing_key_returns_none 未註冊回 None AC-15
同上 test_register_handler_overwrites_same_key 同 key 重註冊覆蓋 AC-23
同上 test_precondition_result_default_passed_no_reason PreconditionResult dataclass 預設值 AC-8

2.3 OSCAL Stage Handlers(4 個,app/grc/service/oscal_stage_handlers.py

Test File Test Method 驗證對象 覆蓋 AC
test_oscal_stage_handlers.py test_planning_handler_key_is_oscal_planning_activate key 字串對齊 stage_objects.complete_handler_key AC-5
同上 test_planning_handler_execute_calls_activate_project mock OscalAuditService.activate_project 被呼叫 + 參數正確 AC-5, AC-6
同上 test_planning_handler_execute_passes_force_flag ctx.force=True 傳給 activate_project AC-9
同上 test_task_execution_handler_key_correct key=oscal.task_execution.launch_audit AC-5
同上 test_task_execution_handler_calls_launch_audit 呼叫 OscalAuditService.launch_audit AC-5, AC-6
同上 test_audit_handler_key_correct key=oscal.audit.confirm_audit AC-5
同上 test_audit_handler_calls_confirm_audit 呼叫 OscalAuditService.confirm_audit AC-5, AC-6
同上 test_poam_handler_key_correct key=oscal.poam.close_round AC-5
同上 test_poam_handler_calls_close_round 呼叫 OscalAuditService.close_round AC-5, AC-6, AC-18
同上 test_handler_propagates_oscal_service_exception 下層 raise → handler 不吞 AC-5

2.4 OSCAL Stage Preconditions(3 個,app/grc/service/oscal_stage_preconditions.py

Test File Test Method 驗證對象 覆蓋 AC
test_oscal_stage_preconditions.py test_tasks_threshold_passed_when_all_complete incomplete=0 → passed=True AC-10
同上 test_tasks_threshold_failed_returns_reason_and_context incomplete=12, total=50 → passed=False + reason_key + context={"incomplete":12} AC-10, AC-8
同上 test_all_controls_verdicted_passes_when_all_done 所有控制項 verdicted + fail/partial 有 finding → passed=True AC-11
同上 test_all_controls_verdicted_fails_when_unverdicted_exists 未判定 → passed=False, reason 對齊 GRC_412003 邏輯 AC-11
同上 test_all_controls_verdicted_fails_when_fail_without_finding fail/partial 無 finding → passed=False, reason 對齊 GRC_412011 AC-11
同上 test_all_poam_closed_passes_when_no_open_poam open=0 → passed=True AC-12
同上 test_all_poam_closed_fails_with_open_count_in_context 有 open → passed=False + context={"open_count": N} AC-12

2.5 StageAdvanceService(核心 app service)

Test File Test Method 驗證對象 覆蓋 AC
test_stage_advance_service.py test_get_current_stage_info_happy_path 回傳 current_stage + progress + precondition + user_can_advance AC-3, AC-4
同上 test_get_current_stage_info_progress_marks_done_current_pending 4 個 stage 狀態正確標記 AC-4
同上 test_get_current_stage_info_user_cannot_advance_when_role_mismatch auditor 在 planning → user_can_advance=False AC-7
同上 test_get_current_stage_info_precondition_attached_for_task_execution task_execution stage 回傳 precondition 結果 AC-8
同上 test_get_current_stage_info_raises_when_ap_has_no_extension AP 無 ext → 404 GRC_AP_NO_WORKFLOW_BINDING AC-13
同上 test_advance_stage_planning_happy_path_manager manager 推 planning → handler.execute 被呼叫 + complete_job 被呼叫 + AP.status → active AC-5, AC-6
同上 test_advance_stage_role_forbidden_auditor_on_planning auditor 推 planning → 403 GRC_STAGE_ROLE_FORBIDDEN AC-7
同上 test_advance_stage_role_forbidden_non_participant 非專案參與者 → 403 GRC_STAGE_ROLE_FORBIDDEN AC-7
同上 test_advance_stage_precondition_failed_returns_412 task_execution 有未完成 task → 412 GRC_STAGE_PRECONDITION_FAILED + reason AC-8
同上 test_advance_stage_force_true_by_manager_bypasses_precondition manager + force=True → 跳過 check 推進成功 AC-9
同上 test_advance_stage_force_true_by_non_manager_rejected auditor 帶 force=True → 仍 403 AC-9
同上 test_advance_stage_calls_handler_before_complete_job handler.execute 先於 workflow complete_job(順序保證資料一致) plan §十一 risk 3
同上 test_advance_stage_no_workflow_binding_returns_404 AP 未綁 workflow → 404 AC-13
同上 test_advance_stage_handler_key_not_registered_returns_400 stage_object.complete_handler_key 在 Registry 找不到 → 400 GRC_STAGE_HANDLER_NOT_REGISTERED AC-15
同上 test_advance_stage_user_task_not_bound_to_stage_object_returns_400 BPMN UserTask 沒 stage code → 400 GRC_STAGE_OBJECT_NOT_BOUND AC-16
同上 test_advance_stage_bpmn_at_end_event_returns_400 已到終點再 advance → 400 GRC_STAGE_NO_NEXT_NODE AC-14
同上 test_advance_stage_bpmn_uses_user_task_main_role_override UserTask 自訂 mainRole=auditor → auditor 可推進;manager 不行 AC-7
同上 test_advance_stage_poam_completion_closes_ap poam handler 走 close_round → AP.status=closed AC-6, AC-18
同上 test_advance_stage_audit_no_poam_path_closes_ap audit → 無 poam path → AP.status=closed AC-6, AC-18

2.6 API Route 層整合測試(api/flow_engine/routes/stage_advance_route.py

Test File Test Method Endpoint 覆蓋 AC
test_api_stage_advance_route.py test_get_stage_info_200_manager GET /project/

/ap//stage/info

AC-3
同上 test_get_stage_info_200_auditor_user_cannot_advance GET 同上,response.user_can_advance=False AC-7
同上 test_get_stage_info_404_when_ap_not_found AP uid 不存在 AC-13
同上 test_get_stage_info_404_when_ap_no_workflow_binding AP 無 ext / workflow_execution_uid 為 NULL AC-13
同上 test_get_stage_info_401_no_jwt 未帶 token 安全基本
同上 test_post_advance_stage_200_manager_planning_to_active POST advance 成功 AC-5, AC-6
同上 test_post_advance_stage_403_auditor_on_planning 角色擋 AC-7
同上 test_post_advance_stage_403_outsider_no_participant 非 project 參與者 AC-7
同上 test_post_advance_stage_412_precondition_failed_payload_has_reason_context response 含 reason_i18n_key + context AC-8
同上 test_post_advance_stage_200_force_true_manager_bypass manager + force=true AC-9
同上 test_post_advance_stage_403_force_true_auditor_rejected auditor force=true AC-9
同上 test_post_advance_stage_400_handler_key_not_registered 400 AC-15
同上 test_post_advance_stage_400_no_next_node EndEvent 後再 advance AC-14
同上 test_post_advance_stage_400_user_task_not_bound UserTask 無 stage code AC-16
同上 test_post_advance_stage_400_invalid_payload force 非 bool / ctx 非 dict 400 基本

2.7 start_oscal_project Step 22 修改

Test File Test Method 驗證對象 覆蓋 AC
test_start_oscal_project_stage_integration.py test_start_creates_ap_extension_row AP 建立後 compliance.assessment_plan_extensions 有新列 AC-1
同上 test_start_main_workflow_execution_created_and_uid_recorded workflow_execution_uid 寫入 ext AC-1, AC-2
同上 test_start_flow_template_snapshot_uid_is_builtin_full_audit snapshot uid 對應 builtin-full-audit 範本 AC-19
同上 test_start_workflow_stops_at_planning_user_task BPMN 當前節點 = planning UserTask AC-2
同上 test_start_ap_status_remains_preparing AP.status 沒被自動推進 AC-2
同上 test_start_workflow_failure_does_not_rollback_ap_creation Step 22 try/except:raise → AP 仍建成,log error(同 Step 7 容錯 pattern) plan §B.5

2.8 EndEvent 收口 / 舊 raw SQL 移除

Test File Test Method 驗證對象 覆蓋 AC
test_end_event_ap_closure.py test_end_event_does_not_modify_ap_status_directly mock BPMN engine 觸發 _on_end_event_reached → AP.status 不被改第二次 AC-17
同上 test_ext_assessment_plan_repo_impl_files_removed grep 確認 domain/flow_engine/repository/i_ext_assessment_plan_repo.pyinfra/.../ext_assessment_plan_repo_impl.py 不存在 AC-17

2.9 Stage Object Seed 補欄位驗證

Test File Test Method 驗證對象 覆蓋 AC
test_stage_object_handler_keys_seed.py test_planning_handler_key_is_oscal_planning_activate 查 DB row AC-5
同上 test_task_execution_precondition_key_is_tasks_threshold 同上 AC-10
同上 test_audit_precondition_key_is_all_controls_verdicted 同上 AC-11
同上 test_poam_precondition_key_is_all_poam_closed 同上 AC-12

2.10 DI Wiring / 架構約束

Test File Test Method 驗證對象 覆蓋 AC
test_stage_registry_di_wiring.py test_grc_container_registers_4_handlers_at_startup 啟動後 Registry 有 4 個 handler key AC-15, AC-23
同上 test_grc_container_registers_3_preconditions_at_startup 3 個 precondition key AC-23
同上 test_flow_engine_module_does_not_import_grc_or_oscal grep domain/flow_engine/ + app/flow_engine/ 不含 from app.grc / from app.oscal import AC-23

2.11 Error code 覆蓋(必檢)

Error Code HTTP 對應測試
GRC_412021 412 2.6 test_post_advance_stage_412_precondition_failed_*
GRC_403050 403 2.6 test_post_advance_stage_403_*
GRC_400050 400 2.6 test_post_advance_stage_400_no_next_node
GRC_404029 404 2.6 test_get_stage_info_404_when_ap_no_workflow_binding
GRC_400051 400 2.6 test_post_advance_stage_400_handler_key_not_registered
GRC_400052 400 2.6 test_post_advance_stage_400_user_task_not_bound

2.12 權限三組驗證(CLAUDE.md 規範)

每個寫入 endpoint 至少三組權限測試:

Endpoint manager auditor 無 participant
POST /stage/advance (planning) 200 ✓ 403 ✓ 403 ✓
POST /stage/advance (task_execution) 200 / 412(依 precondition) ✓ 403 ✓ 403 ✓
POST /stage/advance (audit) 視 BPMN UserTask main_role 覆寫;預設 auditor → 角色相反 ✓ 200 / 412 ✓ 403 ✓
POST /stage/advance (poam) 200 / 412 ✓ 403(預設) ✓ 403 ✓

註:stage 預設 main_roles 來自 default_main_roles;audit 預設 main_role=auditor、其他=manager(依 Spec 1 §3.2 定義)。BPMN UserTask 覆寫 case 在 test_advance_stage_bpmn_uses_user_task_main_role_override 處理。


3. FE 元件測試(Vitest,compliance-manager-fe/,optional)

3.1 FlowPhaseBanner.vuesrc/components/grc/__tests__/

Test Method 驗證對象 覆蓋 AC
renders stage name from i18n key mock stageInfo → 顯示中文名 AC-20
renders 4-dot progress bar with current dot highlighted progress 解析正確 AC-4, AC-20
shows advance button when user_can_advance=true manager / 對應角色 AC-20
hides advance button when user_can_advance=false auditor on planning AC-7, AC-21
disables button when precondition.passed=false (non-manager) reviewer/auditor 無 force AC-20
shows tooltip with reason_i18n_key and context when precondition fails tooltip 文字 AC-20
manager can force-click disabled-looking button → opens ConfirmDialog dialog 出現 AC-9, AC-20
confirms force in dialog → emits advance with force=true payload payload 正確 AC-9
emits stage-advanced event after successful advance parent view 可 refresh AC-20
renders different copy when stage.kind=stateful (task_execution) banner 文案差異 AC-22

3.2 useStageInfo composable(src/composables/__tests__/

Test Method 驗證對象 覆蓋 AC
fetchStageInfo populates stageInfo ref mock service → ref 更新 AC-3
fetchStageInfo sets error on 404 error.value 含 GRC_AP_NO_WORKFLOW_BINDING AC-13
advance with force=false calls service with correct payload payload 結構 AC-5
advance with force=true sends force flag force 傳出 AC-9
advance refetches stageInfo on success call sequence AC-20
loading flag toggles around async ops UX 細節

3.3 View-level smoke(optional,由 E2E 涵蓋大部分)

僅在元件 unit test 不易覆蓋的整合點補;多數 view 改動由 E2E 驗證。


4. E2E BDD 測試(Cucumber + Playwright,compliance-manager-test/

4.1 Feature 檔案

位置features/flow-engine/stage-advance.feature

Feature: Spec 2 — 階段抽象整合(Stage Advance)
  As a 稽核專案的 PM / 稽核員
  I want to 透過 Banner 推進當前階段
  So that AP 的 lifecycle 由 BPMN 流程引擎驅動

  Background:
    Given 系統有一個 manager 帳號 "pm_a" 與 auditor 帳號 "auditor_b"
    And 已建立合規框架 "CMMC-2.0-L1" 與專案 "Spec2-E2E-Project"
    And 專案套用 default 範本 "builtin-full-audit"

  @happy-path
  Scenario: 完整 4 stage 推進到結案
    Given pm_a 登入並進入專案 "Spec2-E2E-Project" 的 AP 規劃頁(settings)
    Then 看到 FlowPhaseBanner 顯示「規劃」階段
    And progress 第 1 點 highlighted
    When pm_a 點擊 Banner 的「啟動專案」
    Then AP.status 變為 "active"
    And Banner 階段名變為「執行任務」
    When pm_a 進入專案總覽頁
    And 所有任務已完成
    And pm_a 點擊 Banner 的「啟動稽核」
    Then AP.status 變為 "auditing"
    When auditor_b 登入並進入稽核頁
    And 所有控制項已 verdicted 且 fail 控制項有 finding
    And auditor_b 點擊 Banner 的「提交稽核」
    Then AP.status 變為 "remediation"
    When pm_a 進入缺失改善頁
    And 所有 POA&M 已 closed
    And pm_a 點擊 Banner 的「完成改善」
    Then AP.status 變為 "closed"
    And Banner 顯示「已結案」

  @precondition-fail
  Scenario: task_execution 階段有未完成任務 — 按鈕 disabled + tooltip
    Given AP.status=active 且有 12 / 50 任務未完成
    When pm_a 進入專案總覽頁
    Then Banner「啟動稽核」按鈕為 disabled 狀態
    And tooltip 顯示「尚有 12 / 50 任務未完成」

  @role-blocking
  Scenario: auditor 在 planning 階段看不到推進按鈕
    Given AP.status=preparing
    When auditor_b 登入並進入專案規劃頁(settings)
    Then Banner 顯示「規劃」階段
    But 不顯示「啟動專案」推進按鈕

  @force-override
  Scenario: manager 透過 ConfirmDialog 強制推進
    Given AP.status=active 且有 12 / 50 任務未完成
    When pm_a 進入總覽頁
    And pm_a 點擊 Banner「啟動稽核」(disabled 但 manager 可點)
    Then 顯示 ConfirmDialog 列出未完成任務數
    When pm_a 確認 ConfirmDialog
    Then AP.status 變為 "auditing"

  @navigation-buttons-intact
  Scenario: 既有 4 個導航按鈕(專案規劃/進入稽核/查看稽核/改善計畫)仍存在
    Given AP.status=active
    When pm_a 進入專案總覽頁
    Then Banner 內不含「啟動稽核」舊按鈕位置(已搬至 Banner)
    But 右上角仍可見「導航按鈕:進入稽核」按鈕(沿用既有 v-if 邏輯)

4.2 Step Definitions 拆解

Step File Step 摘要 對應 Page Object 方法
steps/flow-engine/stage-advance-steps.js Given <role> 登入並進入專案 ".." 的 .. 頁 LoginPage::loginAs() + ProjectNavPage::goToSettings()
同上 Then 看到 FlowPhaseBanner 顯示「<stage>」階段 FlowPhaseBannerComponent::getStageName()
同上 When .. 點擊 Banner 的「<button>」 FlowPhaseBannerComponent::clickAdvance()
同上 Then AP.status 變為 "<status>" ApDetailPage::getApStatus() 或 API assertion
同上 Then Banner「<button>」按鈕為 disabled 狀態 FlowPhaseBannerComponent::isAdvanceDisabled()
同上 And tooltip 顯示「<text>」 FlowPhaseBannerComponent::getTooltipText()
同上 Then 顯示 ConfirmDialog 列出 .. ConfirmDialogComponent::isVisible() + getMessage()
同上 When .. 確認 ConfirmDialog ConfirmDialogComponent::confirm()
同上 Then 不顯示「<button>」推進按鈕 FlowPhaseBannerComponent::hasAdvanceButton()
同上 Then 右上角仍可見「導航按鈕:<text>」按鈕 ProjectOverviewPage::getLegacyNavButtons()

4.3 Page Object 清單

Page Object 路徑 主要 method
FlowPhaseBannerComponent pages/grc/FlowPhaseBannerComponent.js getStageName(), getProgressDotStatus(index), clickAdvance(), isAdvanceDisabled(), getTooltipText(), hasAdvanceButton()
ProjectSettingsPage pages/grc/ProjectSettingsPage.js(新增) gotoSettings(projectUid), banner: FlowPhaseBannerComponent
ProjectOverviewPage pages/grc/ProjectOverviewPage.js(既有,加 banner ref) gotoOverview(), banner, getLegacyNavButtons()
AuditReviewPage pages/grc/AuditReviewPage.js(既有,加 banner ref) gotoAuditPage(), banner
PoamPage pages/grc/PoamPage.js(既有,加 banner ref) gotoPoamPage(), banner
ConfirmDialogComponent pages/common/ConfirmDialogComponent.js(若無則新增) isVisible(), getMessage(), confirm(), cancel()
ApDetailPage(API helper) pages/grc/ApDetailPage.js getApStatus(apUid) via REST API(fast assertion,不走 UI)

4.4 測試資料準備

  • Cucumber Background 透過 BE seeding API(或直接 SQL fixture)建:
    • 1 個專案、1 個 AP(status=preparing)、套用 builtin-full-audit 範本
    • 50 個 task(依 scenario 分配未完成數)
    • 控制項 / verdict / finding / POA&M 狀態依 scenario 預備
  • 推薦:compliance-manager-test/seeds/spec2-e2e/ 放可重用 SQL fixture

4.5 不在 E2E 範圍(已由 BE / FE 元件層覆蓋)

  • AC-13 / AC-14 / AC-15 / AC-16(error code 細節):BE 整合測試已覆蓋,E2E 不重複觸發異常 BPMN 狀態
  • AC-1 / AC-2(DB schema 寫入細節):BE 單元測試已覆蓋
  • AC-23(架構約束 import):靜態檢查,無 E2E 意義

5. Traceability Matrix

AC ID BE Unit BE Integration FE Component E2E 備註
AC-1 ✓ test_assessment_plan_extension_repo.* ✓ test_start_oscal_project_stage_integration DB 層;E2E 不重複
AC-2 ✓ test_start_workflow_stops_at_planning_user_task ✓ Background
AC-3 ✓ test_get_current_stage_info_happy_path ✓ test_get_stage_info_200_manager ✓ useStageInfo.fetchStageInfo ✓ Happy path
AC-4 ✓ test_get_current_stage_info_progress_marks_done_current_pending ✓ renders 4-dot progress bar ✓ progress dot assertion
AC-5 ✓ test_oscal_stage_handlers.* ✓ test_post_advance_stage_200_manager_planning_to_active ✓ Happy path
AC-6 ✓ test_advance_stage_*_happy_path ✓ test_post_advance_stage_200_* ✓ Happy path 4 stage 連推
AC-7 ✓ test_advance_stage_role_forbidden_* ✓ test_post_advance_stage_403_* ✓ hides advance button ✓ @role-blocking
AC-8 ✓ test_advance_stage_precondition_failed_returns_412 ✓ test_post_advance_stage_412_* ✓ shows tooltip with reason ✓ @precondition-fail
AC-9 ✓ test_advance_stage_force_true_by_manager_bypasses_precondition ✓ test_post_advance_stage_200_force_true_manager_bypass ✓ manager can force-click ✓ @force-override
AC-10 ✓ test_tasks_threshold_* ✓ @precondition-fail
AC-11 ✓ test_all_controls_verdicted_* ✓ Happy path(implicit)
AC-12 ✓ test_all_poam_closed_* ✓ Happy path(implicit)
AC-13 ✓ test_get_current_stage_info_raises_when_ap_has_no_extension ✓ test_get_stage_info_404_when_ap_no_workflow_binding ✓ useStageInfo.fetchStageInfo error ⚠️ 無 異常路徑,BE 已驗
AC-14 ✓ test_advance_stage_bpmn_at_end_event_returns_400 ✓ test_post_advance_stage_400_no_next_node ⚠️ 無 異常路徑
AC-15 ✓ test_get_handler_missing_key_returns_none + test_advance_stage_handler_key_not_registered_returns_400 ✓ test_post_advance_stage_400_handler_key_not_registered ⚠️ 無 異常路徑
AC-16 ✓ test_advance_stage_user_task_not_bound_to_stage_object_returns_400 ✓ test_post_advance_stage_400_user_task_not_bound ⚠️ 無 異常路徑
AC-17 ✓ test_end_event_does_not_modify_ap_status_directly + test_ext_assessment_plan_repo_impl_files_removed ✓ Happy path(implicit verify AP.status closed once)
AC-18 ✓ test_advance_stage_poam_completion_closes_ap + test_advance_stage_audit_no_poam_path_closes_ap ✓ Happy path
AC-19 ✓ test_start_flow_template_snapshot_uid_is_builtin_full_audit ✓ Background
AC-20 ✓ FlowPhaseBanner.* ✓ Happy path
AC-21 ⚠️ 限元件層 ✓ @navigation-buttons-intact grep code 確認舊按鈕拆除(人工 / lint)
AC-22 ✓ stage.kind=stateful copy 變化 ✓ Happy path(task_execution stage on overview) MyTasksView 不掛 Banner 由 grep 驗證
AC-23 ✓ test_flow_engine_module_does_not_import_grc_or_oscal ⚠️ 無 架構約束,靜態 check

未覆蓋彙整

  • AC-13/14/15/16 無 E2E:⚠️ 異常路徑、UI 不可達;BE 整合測試已驗,E2E 不重複觸發
  • AC-21 部分:⚠️ 「舊按鈕完全拆除」靠 grep code + E2E @navigation-buttons-intact scenario 雙重驗證;元件層難覆蓋
  • AC-23:⚠️ 架構約束無 E2E 意義;靜態測試 + code review 守

覆蓋率:23 個 AC,至少有一層 test 覆蓋 = 100%。其中 17 個有 E2E 直接驗、6 個僅靠 BE / 元件層(標 ⚠️)。


6. 執行順序與閘門

1. Pre-flight 假設驗證(implementation-plan.md §〇 5 條 grep)
       ↓ 全 pass 才開工
2. BE Phase A.1~A.4 → BE pytest 單元測試(2.1 / 2.2 / 2.9)全綠
       ↓
3. BE Phase B.1~B.7 → BE pytest 整合測試(2.3~2.8 / 2.10~2.12)全綠
       ↓
4. BE manual smoke(curl + dev DB,4 stage 連推到 closed)
       ↓
5. FE Phase C → Vitest 元件測試(3.1 / 3.2)全綠
       ↓
6. FE Phase D → manual smoke(4 個 view 都看到 Banner)
       ↓
7. E2E(compliance-manager-test)→ Cucumber 5 scenario 全綠
       ↓
8. Phase F code review(pr-review-toolkit 4-agent parallel)
       ↓
9. Push + dev DB 完整 rollback / re-migrate / 重啟 BE 重跑 E2E

閘門條件

  • 步驟 3 / 5 / 7 任一全綠才能進下一階段
  • 步驟 8 review 發現 high-severity → 回對應 phase 修
  • 步驟 9 rollback 復原失敗 → 暫停 push 等修補

7. 不在本次測試範圍

明確列出:

  • 壓力測試 / 性能測試:spec 未要求;stage advance 非高頻 API(每個 AP 一輪 4 次)
  • 安全測試(XSS / SQL injection):sqlalchemy parameterized + flask-restful schema 已涵蓋;本 spec 無新增 raw SQL
  • 跨瀏覽器相容:sticking to project default browser matrix(不擴)
  • i18n 切換完整測試:僅驗 4 個新 i18n key(reason_i18n_key)正確帶到 FE;不全量切 en/zh
  • Spec 1 範本 CRUD:已在 Spec 1 test-plan 覆蓋
  • Spec 3 範本 wizard:未實作
  • BPMN loop back PM Dialog:v1 不做
  • 觀察者 / viewer 角色完整 UI 行為:沿用既有 v-if,無新 logic
  • compliance.project_extensions.default_flow_template_uid:Spec 3 範圍

8. 風險與待釐清

風險 影響 緩解 / 待釐清
workflow_executions 表是否支援 main + task 雙層(is_main 欄位) 高 — 影響 AP build 流程 Pre-flight \d compliance.workflow_executions 確認;若缺欄位 → 回 plan 修
@transaction 嵌套(StageAdvanceService → OscalAuditService.confirm_audit → close_round) 中 — 可能 commit 衝突 既有 confirm_audit→close_round 已嵌套運作;新增 test test_advance_stage_calls_handler_before_complete_job 驗順序
BPMN UserTask 自訂 mainRole extension 解析方式 中 — 影響角色覆寫測試 Spec 1 BPMN 編輯器存的 attribute name 待確認(mainRole vs main_roles vs <extensionElements>);test 用 fixture BPMN
Precondition reason_i18n_key 與既有 launch_audit error message 對齊度 中 — UX 一致性 整理 4 個 reason key 對應的既有 GRC error code(412003 / 412005 / 412011);FE i18n file 集中管理
backfill SQL 對既有 dev/stg 環境影響 INSERT ... ON CONFLICT DO NOTHING,可重跑;test 環境 fresh DB 不受影響
pm_decides_loopback placeholder gateway default 行為 Phase B 確認 BPMN engine evaluate 未綁變數的 gateway → 預期走 default flow (→ closed)
Spec 2 落地後 force=true 觸發既有 launch_audit 內部 force 邏輯 OscalAuditService.launch_audit 已支援 force param;handler 直傳即可
Step 22 容錯 (workflow 啟動失敗不 rollback AP) 留下「孤兒 AP」處理 中 — UX 問題 test 涵蓋 test_start_workflow_failure_does_not_rollback_ap_creation;UX 補 retry 入口(follow-up)

9. 測試規模摘要

層級 檔案數 Test method 數(估)
BE Repository / Mapper 2 8
BE Domain Registry / Interface 1 5
BE OSCAL Stage Handlers 1 10
BE OSCAL Stage Preconditions 1 7
BE StageAdvanceService 1 19
BE API Route 整合 1 15
BE start_oscal_project Step 22 1 6
BE EndEvent / 舊檔移除 1 2
BE Stage Object Seed 1 4
BE DI Wiring / 架構約束 1 3
BE 小計 11 79
FE FlowPhaseBanner 元件 1 10
FE useStageInfo composable 1 6
FE 小計 2 16
E2E feature file 1 5 scenario
E2E step / page objects ~7 檔
E2E 小計 ~8 5 scenarios

總計:BE 11 test files / ~79 test methods + FE 2 test files / ~16 test methods + E2E 5 scenarios。


10. 文件版本

版本 日期 變更
v1 2026-05-12 初版 test-plan(Phase 4 產出,依 design.md v2 §九 + implementation-plan.md v1)