blog.dopana

Back

Testing không phải việc “làm sau” — nó là một phần của quy trình phát triển. Code không test là code không hoạt động (bạn chỉ chưa biết thôi).

Pyramid Test#

        ╱  E2E  ╲       ← Chậm, đắt, ít
       ╱─────────╲
      ╱Integration╲     ← Trung bình
     ╱─────────────╲
    ╱  Unit Test    ╲    ← Nhanh, rẻ, nhiều nhất
   ╱─────────────────╲
txt
  • Unit Test: Test function/class riêng lẻ, mock dependencies
  • Integration Test: Test nhiều module cùng nhau, DB thật
  • E2E Test: Test flow user hoàn chỉnh, browser thật

Unit Test với Vitest#

Mock API#

import { vi, it, expect } from 'vitest';
import { fetchUser } from './api';

vi.mock('./api', () => ({
  fetchUser: vi.fn(),
}));

it('returns user when API succeeds', async () => {
  (fetchUser as Mock).mockResolvedValue({ id: 1, name: 'Alice' });
  const result = await fetchUser(1);
  expect(result.name).toBe('Alice');
});
typescript

Integration Test với Supertest#

Component Test với Testing Library#

E2E Test với Playwright#

Coverage#

# Vitest
npx vitest --coverage

# output:
# ------------------------|---------|---------|---------|---------|
# File | % Stmts | % Branch| % Funcs | % Lines |
# ------------------------|---------|---------|---------|---------|
# src/utils/ | 95.45 | 88.89 | 100.00 | 95.45 |
# src/api/ | 92.31 | 100.00 | 85.71 | 92.31 |
# src/components/ | 88.57 | 78.95 | 91.67 | 88.57 |
# ------------------------|---------|---------|---------|---------|
bash

Mục tiêu: > 80% coverage. Nhưng nhớ: coverage % không đồng nghĩa code quality.

Mock Database Cho Integration Test#

CI — Test Trong Pipeline#

test:
  runs-on: ubuntu-latest
  services:
    postgres:
      image: postgres:16-alpine
      env:
        POSTGRES_PASSWORD: test
  steps:
    - uses: actions/checkout@v4
    - run: npm ci
    - run: npm test
      env:
        DATABASE_URL: postgres://postgres:test@localhost:5432/postgres
yaml

Tips#

  • Test behavior, không test implementation — đừng test internal state
  • Mỗi test một concept — nếu test fail, bạn biết ngay cái gì hỏng
  • AAA Pattern: Arrange (setup) → Act (hành động) → Assert (kiểm tra)
  • Fake trước, mock sau — dùng in-memory DB thay vì mock DB
  • Snapshot cho UI — nhưng dùng có chọn lọc, snapshot dễ hỏng

Kết Luận#

Viết test không làm bạn chậm — nó làm bạn nhanh hơn về dài hạn. Bắt đầu với unit test cho logic business, thêm integration test cho API, và E2E cho critical user flow. 80% coverage là đủ — chasing 100% thường lãng phí.

Tài liệu tham khảo#