搜尋開發指南

試試「多租戶」、「啟動」或「outbox」。
搜尋僅使用本站文件,不會傳送至外部服務。

文件目錄

NEXUSPRO / HANDBOOK

測試策略與證據分層

把契約、單元、整合、E2E、瀏覽器與 Apifox 證據放在正確層級,不用一個綠色結果冒充整體驗收。

內容核對 2026-09-28·圖文指南

本章目標

學會為一個改動選擇最小且足夠的測試,並把「程式碼/本機聚焦/整合/E2E/Apifox/部署現場」證據分開報告。命令依目前 Makefile、Go tests 與前端 package scripts 核實;本輪沒有執行業務測試或部署驗收。

前置條件

先讀後端開發規範及前端頁面規範。確認受影響的契約、租戶、資料庫 migration、環境和既有工作區差異;不使用真實密碼、token、內部帳號或 production data 當 fixture。

證據分層

層級主要問題目前入口不能證明
static/type形狀、生成物、命名與編譯Go make ci-core、前端 pnpm typecheck、pnpm lintruntime 資料與登入
unit純函式、service 分支、元件狀態make unit、另跑 go test ./tests/unit/...、Vitest真實 PostgreSQL/外部服務
contractOpenAPI、SQL、migration、路由註冊make contract、前端 contract tests部署版本行為
integration真 DB、RLS、transaction、workermake integration(testcontainers)對外環境與 Apifox
E2Ecompose stack 上的 HTTP 黑箱流程make ci-local測試站/production、前端頁面
Apifox已授權環境的 happy path 與關鍵錯誤make apifox-isolated未跑的斷言或舊 schema
browser/deploy真實版本、租戶、登入與畫面playwright-lan MCP 四寬驗收與部署記錄其他版本或租戶

綠色 unit test 只表示該測試執行的路徑通過。未執行、被 skip、斷言數為零或環境不同,都必須在報告中保留。後端 make integration、make e2e 與 contract 前置的 e2e-static 都經 cmd/testgate -forbid-skip 判定,任何 skip 都算失敗;前端 Vitest 沒有這層保護,要自己看 skipped 數。

後端沒有平台 CI:tests/contract/ci_gate_test.go 禁止加入 .gitlab-ci.yml、.github/workflows 等設定,所有 gate 都在本機以 make 執行。前端 GitLab CI 的 static-check 只跑 pnpm lint 與 pnpm typecheck,pnpm test:run 因既有失敗刻意未納入,所以前端 pipeline 綠不等於測試綠。

後端單元與契約

後端 unit 通常不要求 integration/E2E:

bash
# 工作目錄:nexus-pro-be-plus
go test ./internal/service/... ./internal/api/... -count=1
go test ./tests/unit/... -count=1   # make unit 不包含這個目錄
make contract
make ci-core

Makefile 的 ci-core 依序執行 fmt vet build lint unit contract drift mod-drift migration-structural file-size。其中 unit 只跑 ./cmd/...、./internal/...、./db/...,再用 python3 執行 approved-config-test;tests/unit/...(例如 tests/unit/forminstance)不在 ci-core/ci-local 內,改到相關程式時要另跑 go test ./tests/unit/... 或 make test。drift 比對 sqlc、mapper、config、errcodes 生成物;contract 會先跑 e2e-static,驗證 E2E 素材的封閉契約,不代表真的啟動 compose。第一次執行時,golangci-lint 與 sqlc 會以 go run 下載 Makefile 指定的版本,需要可用的 Go module 來源。

契約測試要鎖:HTTP method/path、request body closed object、permission policy、error code、migration RLS、sqlc 生成狀態和 event handler 1:1 registry(後者由 internal/outbox 的 handler registry 測試負責)。closed object 目前由各域的 OpenAPI helper 檢查;snake_case 命名沒有機械檢查,只能靠 review。不要把實作細節重複到每一個測試;找既有 canonical helper。

新增路由或 migration 時的封閉清單

  • 路由:權限點由 handler 註冊時的 route.Point(...) 宣告,快照在 internal/route/testdata/registry.golden(TestRouteDeclarationSnapshotMatchesGolden 逐字比對,沒有自動更新旗標,要手動改);api/openapi.yaml 沒有結構化的權限欄位。另外 tests/contract/openapi_test.go 的 trackedOpenAPIOperations 與 tests/contract/operator_surface_test.go 的精確路由集合也要加上新的 path/method,任一漏改 make contract 都會失敗。
  • migration:新檔要在 db/migrations/FROZEN.sha256 追加 hash(TestReleasedMigrationHashesMatch),並把 tests/integration/postgres/migrations_test.go 的 latestMigrationVersion 改成新版本;編號須連續且有 goose Down。改 queries 後以 make generate 重生 sqlc 與 mapper,make drift 會比對結果。

PostgreSQL 整合與 RLS

make integration 以 REQUIRE_INTEGRATION=1 執行 ./cmd/db-provision 與 ./tests/integration/...(postgres、redis);PostgreSQL 由 testcontainers 在測試中啟動,所以需要 Docker,但不經 compose。tests/integration/postgres 涵蓋真實 transaction、round-trip、RLS、outbox、workflow 與 domain migration。每個 tenant negative case 都要證明資料沒有越界,不可只測 WHERE tenant_id 的 happy path。

bash
make integration
# 聚焦單支時要自己帶旗標,否則測試會 skip
REQUIRE_INTEGRATION=1 go test ./tests/integration/postgres -run '^TestName$' -count=1

如果缺 Docker、資料庫或認證,命令失敗就代表環境 gate 受阻,不是產品 code pass。migration 測試尤其需要確認實際套用版本、既有資料與 down/還原策略;新增 migration 還要同步 FROZEN.sha256 與 latestMigrationVersion。

E2E 與 compose

make ci-local 的實際順序:

  1. ci-core。
  2. make integration(testcontainers,不經 compose)。
  3. compose-up:e2e-scope 檢查隔離 project/image 名稱,再跑 e2e-static,然後以 docker-compose.yml 疊加 tests/e2e/docker-compose.e2e.yml 執行 up -d --build --wait --wait-timeout 120 api worker。override 讓 PostgreSQL 使用 tmpfs,對外 port 改為隨機本機埠。
  4. make e2e:以 REQUIRE_E2E=1 執行 tests/e2e,同樣經 testgate -forbid-skip。
  5. compose-clean:down --remove-orphans 並刪除該次 image;中途失敗也會執行清理。

compose 的 api/worker healthcheck 打的是 /healthz,所以 --wait 只證明程序存活;API 與 worker 的 /readyz 由 E2E 測試斷言。tests/e2e 是對這個 compose stack 的 HTTP 黑箱測試(含 health/readiness 與資料庫故障注入),不是瀏覽器頁面流程。它證明該次隔離 compose 的流程,不代表共享 test site 或 production。

bash
# 由 Makefile 產生隔離專案與 image;不要手動共用別人的 compose project
make ci-local

若只跑 go test ./tests/e2e 而沒有 REQUIRE_E2E=1 與對版 compose,不能宣稱 E2E gate 通過。驗證 worker 時要確認跑的是重建後 binary,不是舊 image。

前端測試與 MSW

業務前端使用 Vitest、Testing Library、MSW、jsdom。MSW handler 只應照 api/openapi.yaml 與 route registry 寫已註冊路由;mock auth/MSW 只允許 development,不能證明 Keycloak、後端授權或 RLS。

前端 AGENTS.md 的交付門是 lint、typecheck、test:run、deadcode 四項;改 theme、SSR 或 App Router 邊界時再加 production build 與 hydration 檢查。指令優先用 nub run,pnpm 亦可。

bash
# 工作目錄:nexus-pro-web-plus
pnpm typecheck
pnpm test:run features/forms/workflow-preview.contract.test.tsx
pnpm test:run libs/api/client.contract.test.ts
pnpm lint
pnpm deadcode

deadcode 是 knip --include exports,types,duplicates --max-issues 8;門檻只隨實測下降同次下調,調高要有 MR 理由。

workflow-preview.contract.test.tsx 示範空 body、camelCase、undetermined、未知 warning code、409 invalid state、404 和 revision revalidation。transport contract 則測 envelope、casing、request ID、204、FormData、blob error 和 schema drift;這些測試不能代替真實登入。

test/contract/openapiShape.test.ts 與 test/contract/routeRegistry.test.ts 會讀同層的 ../nexus-pro-be-plus(OpenAPI 與 internal/route);沒有這個 checkout 時,前後端對照的斷言以 describe.skipIf 整組跳過,報告要寫 skipped,不能算通過。test/fixtures/routeRegistry.json 是後端路由宣告的副本,後端改頁樹、群組、跨端入口或權限點後,要執行 node scripts/sync-page-tree.mjs 並把 diff 一起送審。

瀏覽器與可及性

瀏覽器驗證要記錄 URL、build/version、登入租戶、viewport、操作步驟、API status/trace、console error 與畫面結果。前端規範要求 UI 交付必驗 1440、1024、720、360 四個寬度,每個寬度都要有截圖、console 與流程證據,缺任一寬度即是交付缺口;窄寬時表格要自身橫捲而不是 body overflow,並確認 focus 可見、鍵盤可用、錯誤非只靠顏色。

瀏覽器自動化、截圖與 console/network 檢查統一使用已綁定的 playwright-lan MCP,不啟動本機自動化瀏覽器。MCP 的瀏覽器在服務端,localhost 指向服務端而不是你的機器,要改用 MCP 可達的位址;MCP 或網路不可用時標記 BLOCKED,繼續其他可獨立執行的檢查。

bash
# 前端本地啟動形狀;交給 MCP 驗收前先確認它連得到這個位址
pnpm dev

未登入被 redirect、後端 401、MSW fixture 或 selector 找不到,應在證據中說明阻塞原因;不能截圖後推測功能已完成。

Apifox 聯調

後端每次新增或修改可呼叫 endpoint,都要在 Apifox 建/改場景並加入套件 29010。交付驗證用 make apifox-isolated:它建置目前工作樹的獨立 compose,以 apifoxfixture build tag 的 TestPrepareApifox 建立管理員、self-only 員工與確定的假勤資料,建立只含本次 loopback origin 的臨時雲端環境後執行 make apifox-test,最後刪除臨時環境並清理 compose。它會 unset 繼承的 NEXUS_DEV_PASSWORD 等變數,身分全由私有 fixture 提供;前提是 Docker、已登入的 Apifox CLI、既有 .env 與專案的雲端寫入授權。

bash
# 工作目錄:nexus-pro-be-plus;本輪未執行
make apifox-isolated

# 手動執行:APIFOX_RUNTIME_VARS 指向私有 fixture JSON,APIFOX_ENV 指向與它匹配的環境
APIFOX_RUNTIME_VARS=/path/to/private/runtime.json make apifox-test APIFOX_ENV=<匹配的環境 id>

make apifox-test 由 tools/run_apifox.py 執行:除了登入密碼,還要求 myleave/attendance 等 fixture 變數,缺任何一個就在送出請求前以 exit 2 拒絕,所以只設 NEXUS_DEV_PASSWORD 不夠(後端 AGENTS.md 與 deploy/BOOTSTRAP.md 仍寫舊流程,以 Makefile 為準)。報告預設寫到 .apifox/reports,隔離流程則在結束時印出日誌目錄。密碼只從環境變數或 0600 的私有 fixture 檔來,不可放雲端或版控。

除了 CLI success,還要看報告中的斷言數大於零、場景命中正確版本/租戶,並保留 4xx 關鍵錯誤驗證。Apifox 內建的響應結構校驗目前不可信,契約守門仍以 tests/contract/openapi_* 為準。沒有前置授權時,誠實回報「場景已建、斷言未驗」,不把 ci-local 綠當 Apifox 綠。

預期結果、常見錯誤與相關文件

預期結果: 每個改動都有最小 unit/contract,資料庫改動有 integration/RLS,跨服務流程有 E2E,對外端點有 Apifox,部署行為另有版本與環境證據。

常見錯誤:只看單元綠、以為 ci-core 已涵蓋 tests/unit/...、把 skipped 當 passed(包括缺後端 sibling 時的前端 contract 測試)、用 mock 驗登入、只設 NEXUS_DEV_PASSWORD 就跑 make apifox-test、Apifox 斷言數 0、新增路由或 migration 卻漏改封閉清單、把前端 pipeline 綠當測試綠、共用 dirty compose、未 rebuild image、或只測錯誤不測真正成功。交付格式與部署差異見測試與交付,異常排查見常見問題。

內容來源與核實範圍

以下路徑相對於所列業務倉庫;核實層級為「已讀原始碼」,不是本輪業務測試或部署驗收。

  • nexus-pro-be-plus/Makefile
  • nexus-pro-be-plus/tests/contract
  • nexus-pro-be-plus/tests/contract/ci_gate_test.go
  • nexus-pro-be-plus/tests/integration/postgres
  • nexus-pro-be-plus/tests/integration/postgres/migrations_test.go
  • nexus-pro-be-plus/tests/e2e
  • nexus-pro-be-plus/tests/e2e/docker-compose.e2e.yml
  • nexus-pro-be-plus/db/migrations/FROZEN.sha256
  • nexus-pro-be-plus/internal/route/testdata/registry.golden
  • nexus-pro-be-plus/tools/run_apifox.py
  • nexus-pro-be-plus/tools/apifox_isolated.sh
  • nexus-pro-be-plus/docs/testing/apifox-isolated.md
  • nexus-pro-be-plus/memory/dev-log/2026-09-24.md
  • nexus-pro-web-plus/package.json
  • nexus-pro-web-plus/vitest.config.ts
  • nexus-pro-web-plus/AGENTS.md
  • nexus-pro-web-plus/.gitlab-ci.yml
  • nexus-pro-web-plus/test/msw
  • nexus-pro-web-plus/test/contract
  • nexus-pro-web-plus/scripts/sync-page-tree.mjs
  • nexus-pro-web-plus/features/forms/workflow-preview.contract.test.tsx
NexusPro 開發指南以程式碼為準 · 以驗證為據