HUAN 讙 · 開發者

測試

HUAN 的測試不只是「編譯得過」。

pnpm test        # 單元與整合測試
pnpm test:e2e    # Playwright 端對端測試

層次

層次範圍需要的環境
單元測試共用套件的純邏輯
整合測試Server 的 API 與資料庫PostgreSQL、RustFS
Worker 測試真實的 FFmpeg 轉檔PostgreSQL、RustFS、FFmpeg
元件測試Admin 的 React 元件無(jsdom)
端對端測試瀏覽器操作完整流程全部

需要的環境不存在時,測試會明確跳過並印出原因,不會假裝通過。

單元測試

集中在幾個一旦錯掉就很難察覺的地方:

版面分割樹packages/layout-engine)——分割、刪除、交換、序列化往返,以及幾何計算在 1920×1080、1280×720、3840×2160 與 1080×1920 四種畫布上的實際數值。70/30 在 1920 寬上就是 1344 與 576,測試斷言的是這個數字,不是「差不多」。

排程判定packages/shared)——時區換算、跨午夜的錨定日期、日期區間、日光節約時間切換,以及衝突決勝的每一條規則。特別測「同一組輸入永遠得到同一個結果」——把排程用不同順序傳進去必須得到同一個答案。

TOTPpackages/shared)——RFC 4226 與 RFC 6238 的官方測試向量,加上時鐘誤差容忍與重放拒絕。

退避packages/shared)——指數成長、上限封頂、抖動範圍。

環境變數packages/config)——預設值、必填檢查、格式驗證。

Server 整合測試

app.inject() 對真正的 Fastify 實例發請求,接的是真正的 PostgreSQL 與 RustFS。

涵蓋登入成功與失敗、速率限制、TOTP 完整流程、復原碼只能用一次、權限邊界、配對流程、版面發布、排程 CRUD、素材上傳流程、裝置 ACK 的雜湊驗證,以及刪除被引用的素材會被擋下來。

Worker 測試

測試素材由 FFmpeg 自己產生:

ffmpeg -f lavfi -i testsrc=duration=2:size=1280x720:rate=30

repository 裡不放任何大型或有版權的影片。

測試斷言的是實際的輸出屬性:播放版本是 H.264、yuv420p、不超過 1920×1080、不超過 30fps、有 faststart,而且 640×360 的來源不會被放大

佇列的測試驗證 FOR UPDATE SKIP LOCKED 真的讓兩個並行的取件拿到不同的工作、失敗的工作會退避重試、被強制終止的工作會被回收。

Admin 元件測試

vitest 加 Testing Library(jsdom)。

涵蓋認證守衛的重導、版面編輯器的分割與交換操作、比例拖曳的座標換算與夾制、素材上傳的各個狀態,以及排程表單的驗證。

端對端測試

Playwright,跑完整的流程:

登入

建立版面

分割區塊

放入內容

發布

配對模擬裝置

建立排程

模擬裝置(@huan/device-sim)讓這件事不需要真的 Raspberry Pi。它走的是和 Electron 播放器完全相同的同步引擎,因此測到的行為是真的。

文件截圖

pnpm docs:screenshots

用 Playwright 對種子環境擷取真實的產品畫面。種子資料是決定性的,因此每次產生的截圖內容一致,不會讓文件的圖片在每次執行後都不一樣。

文件裡不放示意圖或 placeholder。

CI

.github/workflows/ci.yml 在每次 push 與 PR 上執行:

格式檢查 → 建置共用套件 → migration → 型別檢查 → 測試 → 建置 → 文件建置

外加獨立的端對端測試 job 與 Docker 映像建置驗證。

PostgreSQL 與 RustFS 以 GitHub Actions 的 service container 提供,FFmpeg 用 apt 安裝。