Skip to content

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 requirement

Lab: 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 passes

Phầ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, OWASP

Lab: 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:coverage

Phầ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 →

Powered by CodyMaster × VitePress