dramaling-vocab-learning/複習功能單元測試開發計劃.md

7.6 KiB

複習功能單元測試開發計劃

🎯 為什麼需要單元測試

複習功能的複雜性挑戰

  1. 5個互相依賴的 Zustand Store - 狀態同步複雜
  2. 7種不同測驗模式 - 邏輯分支繁多
  3. 智能優先級算法 - 複雜計算邏輯
  4. API 和 Mock 雙模式 - 環境依賴複雜
  5. CEFR 自適應分配 - 業務邏輯複雜

手動測試的局限性

  • 耗時: 每次改動需要重複測試所有流程
  • 遺漏: 複雜分支容易漏測
  • 回歸: 新功能可能破壞舊功能
  • 邊界: 難以測試所有邊界條件
  • 並發: 無法測試狀態競爭條件

🔧 測試框架設置方案

推薦技術棧

{
  "測試框架": "Vitest (更快的 Jest 替代)",
  "UI測試": "@testing-library/react",
  "Store測試": "zustand 原生測試支援",
  "Mock工具": "MSW (Mock Service Worker)",
  "覆蓋率": "vitest/coverage"
}

安裝命令

# 測試框架
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 測試重點

describe('useReviewDataStore', () => {
  test('loadDueCards 成功載入數據')
  test('loadDueCards 處理 API 失敗')
  test('測試模式使用 Mock 數據')
  test('resetData 正確重置狀態')
  test('findCardById 正確查找詞卡')
})

useTestQueueStore 測試重點

describe('useTestQueueStore', () => {
  test('initializeTestQueue 正確生成測驗項目')
  test('CEFR 分配邏輯正確')
  test('測試模式簡化邏輯')
  test('智能優先級計算')
  test('skipCurrentTest 正確重排隊列')
  test('markTestCompleted 狀態更新')
  test('goToNextTest 導航邏輯')
})

useTestResultStore 測試重點

describe('useTestResultStore', () => {
  test('updateScore 正確計算分數')
  test('recordTestResult 成功記錄')
  test('測試模式跳過 API')
  test('getAccuracyPercentage 計算正確')
  test('resetScore 重置功能')
})

🎭 組件測試策略

ReviewRunner 集成測試

describe('ReviewRunner', () => {
  test('正確渲染當前測驗組件')
  test('答題流程完整性')
  test('導航按鈕狀態管理')
  test('錯誤處理顯示')
  test('進度更新正確性')
})

測驗組件測試

describe('FlipMemoryTest', () => {
  test('翻卡動畫觸發')
  test('信心度選擇功能')
  test('onConfidenceSubmit 回調')
  test('disabled 狀態處理')
})

🌐 API Mock 策略

MSW 設置

// __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
    }))
  })
]

測試模式驗證

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% 覆蓋率

關鍵指標

# 覆蓋率報告
npm run test:coverage

# 目標覆蓋率
- 函數覆蓋率: 85%+
- 語句覆蓋率: 80%+
- 分支覆蓋率: 75%+
- 行覆蓋率: 80%+

🚀 測試驅動開發流程

Red-Green-Refactor

  1. Red: 先寫失敗的測試
  2. Green: 寫最少代碼讓測試通過
  3. Refactor: 重構代碼,保持測試通過

Store 開發流程

// 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 配置

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

本地開發腳本

{
  "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. 用戶交互測試

您想要我立即開始設置測試環境嗎?我可以幫您安裝依賴並創建第一批核心測試文件。


測試是投資,不是成本 - 長遠來看會大幅提升開發效率和代碼品質! 🚀