305 lines
7.6 KiB
Markdown
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. 用戶交互測試
|
|
|
|
**您想要我立即開始設置測試環境嗎?我可以幫您安裝依賴並創建第一批核心測試文件。**
|
|
|
|
---
|
|
|
|
*測試是投資,不是成本 - 長遠來看會大幅提升開發效率和代碼品質!* 🚀 |