# 複習功能單元測試開發計劃 ## 🎯 **為什麼需要單元測試** ### **複習功能的複雜性挑戰** 1. **5個互相依賴的 Zustand Store** - 狀態同步複雜 2. **7種不同測驗模式** - 邏輯分支繁多 3. **智能優先級算法** - 複雜計算邏輯 4. **API 和 Mock 雙模式** - 環境依賴複雜 5. **CEFR 自適應分配** - 業務邏輯複雜 ### **手動測試的局限性** - ❌ **耗時**: 每次改動需要重複測試所有流程 - ❌ **遺漏**: 複雜分支容易漏測 - ❌ **回歸**: 新功能可能破壞舊功能 - ❌ **邊界**: 難以測試所有邊界條件 - ❌ **並發**: 無法測試狀態競爭條件 --- ## 🔧 **測試框架設置方案** ### **推薦技術棧** ```json { "測試框架": "Vitest (更快的 Jest 替代)", "UI測試": "@testing-library/react", "Store測試": "zustand 原生測試支援", "Mock工具": "MSW (Mock Service Worker)", "覆蓋率": "vitest/coverage" } ``` ### **安裝命令** ```bash # 測試框架 npm install -D vitest @vitejs/plugin-react npm install -D @testing-library/react @testing-library/jest-dom npm install -D @testing-library/user-event # Mock 和工具 npm install -D msw npm install -D @vitest/coverage-v8 # TypeScript 支援 npm install -D @types/testing-library__jest-dom ``` --- ## 📁 **測試目錄結構** ``` frontend/ ├── __tests__/ # 測試根目錄 │ ├── setup.ts # 測試設置 │ ├── mocks/ # Mock 文件 │ │ ├── handlers.ts # MSW handlers │ │ └── zustand.ts # Store mocks │ └── utils/ # 測試工具 │ ├── test-utils.tsx # React 測試工具 │ └── store-utils.ts # Store 測試工具 │ ├── store/review/ │ └── __tests__/ # Store 測試 │ ├── useReviewDataStore.test.ts │ ├── useTestQueueStore.test.ts │ ├── useTestResultStore.test.ts │ ├── useReviewSessionStore.test.ts │ └── useReviewUIStore.test.ts │ ├── components/review/ │ └── __tests__/ # 組件測試 │ ├── ReviewRunner.test.tsx │ ├── ProgressTracker.test.tsx │ └── review-tests/ │ ├── FlipMemoryTest.test.tsx │ └── VocabChoiceTest.test.tsx │ └── lib/services/review/ └── __tests__/ # Service 測試 └── reviewService.test.ts ``` --- ## 🧪 **Store 測試策略** ### **useReviewDataStore 測試重點** ```typescript describe('useReviewDataStore', () => { test('loadDueCards 成功載入數據') test('loadDueCards 處理 API 失敗') test('測試模式使用 Mock 數據') test('resetData 正確重置狀態') test('findCardById 正確查找詞卡') }) ``` ### **useTestQueueStore 測試重點** ```typescript describe('useTestQueueStore', () => { test('initializeTestQueue 正確生成測驗項目') test('CEFR 分配邏輯正確') test('測試模式簡化邏輯') test('智能優先級計算') test('skipCurrentTest 正確重排隊列') test('markTestCompleted 狀態更新') test('goToNextTest 導航邏輯') }) ``` ### **useTestResultStore 測試重點** ```typescript describe('useTestResultStore', () => { test('updateScore 正確計算分數') test('recordTestResult 成功記錄') test('測試模式跳過 API') test('getAccuracyPercentage 計算正確') test('resetScore 重置功能') }) ``` --- ## 🎭 **組件測試策略** ### **ReviewRunner 集成測試** ```typescript describe('ReviewRunner', () => { test('正確渲染當前測驗組件') test('答題流程完整性') test('導航按鈕狀態管理') test('錯誤處理顯示') test('進度更新正確性') }) ``` ### **測驗組件測試** ```typescript describe('FlipMemoryTest', () => { test('翻卡動畫觸發') test('信心度選擇功能') test('onConfidenceSubmit 回調') test('disabled 狀態處理') }) ``` --- ## 🌐 **API Mock 策略** ### **MSW 設置** ```typescript // __tests__/mocks/handlers.ts export const handlers = [ rest.get('/api/flashcards/due', (req, res, ctx) => { return res(ctx.json({ success: true, data: mockDueCards })) }), rest.post('/api/flashcards/test-completion', (req, res, ctx) => { return res(ctx.json({ success: true })) }) ] ``` ### **測試模式驗證** ```typescript test('測試模式跳過真實 API', async () => { // Mock window.location.search Object.defineProperty(window, 'location', { value: { search: '?test=true' } }) const store = useReviewDataStore.getState() await store.loadDueCards() expect(store.dueCards).toEqual(mockDueCards) }) ``` --- ## 📊 **測試覆蓋率目標** ### **階段性目標** - **第一階段** (1週): Store 層 85% 覆蓋率 - **第二階段** (1週): 組件層 80% 覆蓋率 - **第三階段** (1週): 集成測試 70% 覆蓋率 ### **關鍵指標** ```bash # 覆蓋率報告 npm run test:coverage # 目標覆蓋率 - 函數覆蓋率: 85%+ - 語句覆蓋率: 80%+ - 分支覆蓋率: 75%+ - 行覆蓋率: 80%+ ``` --- ## 🚀 **測試驅動開發流程** ### **Red-Green-Refactor** 1. **Red**: 先寫失敗的測試 2. **Green**: 寫最少代碼讓測試通過 3. **Refactor**: 重構代碼,保持測試通過 ### **Store 開發流程** ```typescript // 1. 先寫測試 test('initializeTestQueue 應該根據 CEFR 正確分配測驗', () => { const store = useTestQueueStore.getState() store.initializeTestQueue(mockCards, []) expect(store.testItems).toHaveLength(6) // 3卡 * 2測驗 expect(store.currentMode).toBe('flip-memory') }) // 2. 實現功能 // 3. 重構優化 ``` --- ## 🔄 **CI/CD 整合** ### **GitHub Actions 配置** ```yaml name: 測試 on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: '18' - run: npm ci - run: npm run test - run: npm run test:coverage ``` ### **本地開發腳本** ```json { "scripts": { "test": "vitest", "test:watch": "vitest --watch", "test:coverage": "vitest --coverage", "test:ui": "vitest --ui" } } ``` --- ## 📈 **測試效益預期** ### **開發效率提升** - ✅ **快速回饋**: 秒級發現問題 - ✅ **信心重構**: 安全修改代碼 - ✅ **文檔化**: 測試即規格說明 - ✅ **減少 Debug**: 問題早期發現 ### **代碼品質提升** - ✅ **模組化**: 測試推動更好設計 - ✅ **邊界處理**: 覆蓋更多邊界情況 - ✅ **錯誤處理**: 異常情況測試 - ✅ **性能保證**: 性能回歸檢測 --- ## 🎯 **立即行動計劃** ### **第一步: 設置測試環境** 1. 安裝測試依賴 2. 配置 Vitest 3. 設置基礎 Mock 4. 寫第一個 Store 測試 ### **第二步: 核心功能測試** 1. useReviewDataStore 完整測試 2. useTestQueueStore 邏輯測試 3. Mock 數據驗證測試 ### **第三步: 組件測試** 1. ReviewRunner 集成測試 2. 基礎測驗組件測試 3. 用戶交互測試 **您想要我立即開始設置測試環境嗎?我可以幫您安裝依賴並創建第一批核心測試文件。** --- *測試是投資,不是成本 - 長遠來看會大幅提升開發效率和代碼品質!* 🚀