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

305 lines
7.6 KiB
Markdown

# 複習功能單元測試開發計劃
## 🎯 **為什麼需要單元測試**
### **複習功能的複雜性挑戰**
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. 用戶交互測試
**您想要我立即開始設置測試環境嗎?我可以幫您安裝依賴並創建第一批核心測試文件。**
---
*測試是投資,不是成本 - 長遠來看會大幅提升開發效率和代碼品質!* 🚀