Chương 9: Testing Như Thở — TDD & Test Gate

"Hà nói: 'Tôi từng test bằng tay — click 500 lần mỗi ngày. Bây giờ, 1 command chạy 50 tests trong 3 giây. Tôi muốn quay lại click tay không? KHÔNG BAO GIỜ.'"
🎯 Mục tiêu
- Master TDD Red-Green-Refactor cycle
- Build 5-Layer Test Gate cho TeamFlow
- Setup CI pipeline (GitHub Actions)
- Fix tất cả bugs Sprint 1 bằng TDD
Phần 1: TDD Iron Law (20 phút)
The Cycle
RED → Write a failing test (describe WHAT should happen)
GREEN → Write minimal code to pass the test
REFACTOR → Clean up code, keep tests green
REPEAT → Next requirementLab: Fix Bug #1 with TDD
bash
# RED: Write test that SHOULD pass but DOESN'T
antigravity "@cm-tdd Write test proving Bug #1 (empty name):
it('should reject project with empty name', async () => {
const res = await request(app)
.post('/api/projects')
.set('Authorization', 'Bearer ' + token)
.send({ name: '', description: 'test' })
expect(res.status).toBe(400)
expect(res.body.error).toBeDefined()
})
"bash
npm test # RED ❌ — test fails (bug exists)bash
# GREEN: Fix the code
# Add validation: z.string().min(1, 'Name is required')
npm test # GREEN ✅ — test passesPhần 2: 5-Layer Test Gate (40 phút)
Architecture
Layer 1: Frontend Safety → DOM structure, accessibility
Layer 2: API Routes → Supertest, HTTP codes, payloads
Layer 3: Business Logic → Unit tests, edge cases
Layer 4: i18n Sync → Key consistency vi/en
Layer 5: Security Scan → Secrets, dependencies, OWASPLab: Build All 5 Layers
bash
antigravity "@cm-test-gate Build 5-layer test gate for TeamFlow:
test/
├── layer1-frontend.test.ts ← DOM, a11y
├── layer2-api.test.ts ← Supertest routes
├── layer3-business.test.ts ← Model logic
├── layer4-i18n.test.ts ← Translation sync
└── layer5-security.test.ts ← Secret scan
Requirements:
- Layer 1: Check index.html has valid structure, no broken links
- Layer 2: All CRUD endpoints return correct status codes
- Layer 3: Project/Task models handle edge cases
- Layer 4: en.json and vi.json have matching keys
- Layer 5: No hardcoded secrets, .env.example exists"Test Scripts
json
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"test:layer1": "vitest run test/layer1-frontend.test.ts",
"test:layer2": "vitest run test/layer2-api.test.ts",
"test:layer3": "vitest run test/layer3-business.test.ts",
"test:layer4": "vitest run test/layer4-i18n.test.ts",
"test:layer5": "vitest run test/layer5-security.test.ts",
"test:gate": "vitest run && echo '✅ ALL GATES PASSED'"
}
}Phần 3: GitHub Actions CI (20 phút)
yaml
# .github/workflows/test.yml
name: Test Gate
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run test:gate
- run: npm run test:coveragePhần 4: Coverage Report (10 phút)
bash
npm run test:coverage
# Target: 80%+ coverage
# Focus: models/ and middleware/ should be 90%+
# Lower priority: routes/ (integration tested via Layer 2)Homework
- [ ] 5 test layers created
- [ ] All bugs fixed via TDD
- [ ] 80%+ coverage
- [ ] CI pipeline running on GitHub
Chương tiếp: Collaboration — Comments & Activity →