# Trang 5.7: Tự động hóa kiểm thử mã nguồn với /test.

## 1. Mục đích

**`/test`** là workflow để tự động hóa toàn bộ vòng đời kiểm thử — từ tạo test case, chạy bộ test hiện có, đến báo cáo độ bao phủ (coverage).

> **Triết lý:** Code không có test = code chưa hoàn chỉnh. `/test` giúp đội ngũ duy trì tiêu chuẩn kiểm thử mà không cần mất nhiều thời gian viết test thủ công.

---

## 2. Các chức năng của `/test`

<div class="my-4 rounded-lg overflow-hidden border border-gray-500/20 [&_thead_tr:first-child_th:first-child]:border-t-0 [&_thead_tr:first-child_th:first-child]:border-l-0 [&_thead_tr:first-child_th:last-child]:border-t-0 [&_thead_tr:first-child_th:last-child]:border-r-0 [&_tbody_tr:last-child_td:first-child]:border-b-0 [&_tbody_tr:last-child_td:first-child]:border-l-0 [&_tbody_tr:last-child_td:last-child]:border-b-0 [&_tbody_tr:last-child_td:last-child]:border-r-0 [&_thead_tr:first-child_th]:border-t-0 [&_tbody_tr:last-child_td]:border-b-0 [&_th:first-child]:border-l-0 [&_td:first-child]:border-l-0 [&_th:last-child]:border-r-0 [&_td:last-child]:border-r-0" id="bkmrk-c%C3%BA-ph%C3%A1p-ch%E1%BB%A9c-n%C4%83ng-%2Ft"><table class="min-w-full border-separate border-spacing-0"><thead><tr><th class="bg-gray-500/20 px-3 py-2 text-left font-medium leading-snug border border-gray-500/20">Cú pháp</th><th class="bg-gray-500/20 px-3 py-2 text-left font-medium leading-snug border border-gray-500/20">Chức năng</th></tr></thead><tbody><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">`/test`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">Chạy toàn bộ test suite hiện có</td></tr><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">`/test [file hoặc thư mục]`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">Tạo test cases cho file cụ thể</td></tr><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">`/test coverage`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">Báo cáo tỉ lệ bao phủ (coverage report)</td></tr><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">`/test --watch`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">Chế độ live — tự chạy lại khi code thay đổi</td></tr></tbody></table>

</div>---

## 3. Cách `/test` phân tích và tạo test

Khi nhận lệnh `/test [file]`, AI sẽ:

```html
1. Đọc toàn bộ nội dung file được chỉ định
│
▼
2. Xác định tất cả functions và classes cần test
│
▼
3. Phân tích input/output, edge cases, và error paths
│
▼
4. Tạo test file tương ứng với bộ test đầy đủ:
- Happy path (trường hợp bình thường)
- Error cases (xử lý lỗi)
- Edge cases (giá trị biên)
- Null/undefined inputs
│
▼
5. Chạy test vừa tạo và báo cáo kết quả
```

---

## 4. Ví dụ phiên làm việc thực tế

### Ví dụ 1: Tạo test cho authentication service

```html
👤 Bạn: /test src/services/auth.ts


🤖 AI:
📖 Đang phân tích auth.ts...


Tìm thấy 4 functions cần test:
- login(email, password): Promise<User>
- register(userData): Promise<User>
- verifyToken(token): boolean
- resetPassword(email): Promise<void>


🧪 Đang tạo test cases...


login():
✅ Trả về User khi credentials đúng
✅ Throw AuthError khi email không tồn tại
✅ Throw AuthError khi sai mật khẩu
✅ Throw ValidationError khi email không hợp lệ


register():
✅ Tạo User mới và trả về object
✅ Throw DuplicateError khi email đã tồn tại
✅ Hash password trước khi lưu (không lưu plaintext)
✅ Validate required fields


verifyToken():
✅ Trả về true với token hợp lệ
✅ Trả về false với token hết hạn
✅ Trả về false với token giả mạo
✅ Xử lý null/undefined input


resetPassword():
✅ Gửi email reset khi user tồn tại
✅ Không tiết lộ user không tồn tại (security)


📄 Đã tạo: tests/auth.test.ts (12 test cases)


🏃 Đang chạy tests...


✅ 12/12 PASSED
📊 Coverage: 95% (Statements), 91% (Branches)
```

### Ví dụ 2: Chạy toàn bộ test suite

```html
👤 Bạn: /test


🤖 AI:
🏃 Đang chạy toàn bộ test suite...


✅ auth.test.ts — 12/12 passed (0.8s)
✅ orders.test.ts — 8/8 passed (1.2s)
❌ products.test.ts — 5/7 passed (FAILED)
FAIL: "calculateDiscount returns 0 for expired coupons"
Expected: 0
Received: 10
✅ users.test.ts — 6/6 passed (0.5s)


📊 Summary:
Tests: 31 passed, 2 failed
Coverage: 78%


❌ 2 tests failed. Gợi ý: chạy /debug để điều tra calculateDiscount.
```

### Ví dụ 3: Xem coverage report

```html
👤 Bạn: /test coverage


🤖 AI:
📊 Coverage Report


File | Stmts | Branch | Funcs | Lines
------------------------|-------|--------|-------|------
src/services/auth.ts | 95% | 91% | 100% | 95%
src/services/orders.ts | 82% | 75% | 88% | 82%
src/utils/validators.ts | 60% | 45% | 70% | 60%


⚠️ validators.ts có coverage thấp (60%).
Gợi ý: chạy /test src/utils/validators.ts để bổ sung test.
```

---

## 5. Các nguyên lý kiểm thử được áp dụng

### AAA Pattern (Arrange-Act-Assert)

Mọi test case đều theo cấu trúc:

```typescript
typescript
it('login returns User khi credentials đúng', async () => {
// Arrange — Chuẩn bị dữ liệu test
const mockUser = { email: 'test@example.com', password: 'hashed' };
mockDB.findUser.mockResolvedValue(mockUser);


// Act — Thực hiện hành động cần test
const result = await login('test@example.com', 'correct-password');


// Assert — Kiểm tra kết quả
expect(result).toEqual(expect.objectContaining({ email: 'test@example.com' }));
expect(result.password).toBeUndefined(); // Không trả về password
});
```

### Test hành vi, không test implementation

<div class="relative whitespace-pre-wrap word-break-all my-2 rounded-lg bg-list-hover-subtle border border-gray-500/20" id="bkmrk--4" node="[object Object]"><div class="min-h-7 relative box-border flex flex-row items-center justify-between rounded-t border-b border-gray-500/20 px-2 py-0.5">  
</div><div class="p-3"><div class="w-full h-full text-xs cursor-text"><div class="code-block"><div class="code-line" data-line-end="5" data-line-number="5" data-line-start="5"><div class="line-content"></div></div></div></div></div></div>```typescript
typescript
// ❌ Test implementation (dễ vỡ khi refactor)
expect(service._privateMethod).toHaveBeenCalled();


// ✅ Test hành vi (bền vững)
expect(result.email).toBe('user@example.com');
```

### Kim tự tháp kiểm thử

<div class="relative whitespace-pre-wrap word-break-all my-2 rounded-lg bg-list-hover-subtle border border-gray-500/20" id="bkmrk--5" node="[object Object]"><div class="p-3"><div class="w-full h-full text-xs cursor-text"><div class="code-block"><div class="code-line" data-line-end="1" data-line-number="1" data-line-start="1">  
</div><div class="code-line" data-line-end="7" data-line-number="7" data-line-start="7"><div class="line-content"></div></div></div></div></div></div>```html
       /\
      /E2E\ (ít nhất, chậm nhất, tốn kém nhất)
     /------\
    /Integration\ (vừa phải)
   /------------\
  / Unit Tests \ (nhiều nhất, nhanh nhất, rẻ nhất)
/________________\
```

---

## 6. Mẹo kiểm thử hiệu quả

### Luôn kiểm tra edge cases

Sau khi AI tạo test, yêu cầu thêm:

```html
"Thêm test cases cho:
- Input rỗng (empty string, [], {})
- Giá trị giới hạn (0, -1, MAX_INT)
- Null và undefined
- Chuỗi unicode và ký tự đặc biệt"
```

### Tích hợp vào quy trình `/enhance`

```html
bash
# Sau mỗi lần thêm tính năng mới:
/test [file vừa tạo] # Tạo test cho code mới
/test # Chạy toàn bộ để kiểm tra regression
```

### Yêu cầu mock đúng cách

```html
"/test src/services/payment.ts
Lưu ý: mock VNPay API, không gọi endpoint thực.
Và mock database, không dùng test database."
```

---

## 7. Frameworks được hỗ trợ

<div class="my-4 rounded-lg overflow-hidden border border-gray-500/20 [&_thead_tr:first-child_th:first-child]:border-t-0 [&_thead_tr:first-child_th:first-child]:border-l-0 [&_thead_tr:first-child_th:last-child]:border-t-0 [&_thead_tr:first-child_th:last-child]:border-r-0 [&_tbody_tr:last-child_td:first-child]:border-b-0 [&_tbody_tr:last-child_td:first-child]:border-l-0 [&_tbody_tr:last-child_td:last-child]:border-b-0 [&_tbody_tr:last-child_td:last-child]:border-r-0 [&_thead_tr:first-child_th]:border-t-0 [&_tbody_tr:last-child_td]:border-b-0 [&_th:first-child]:border-l-0 [&_td:first-child]:border-l-0 [&_th:last-child]:border-r-0 [&_td:last-child]:border-r-0" id="bkmrk-framework-file-patte"><table class="min-w-full border-separate border-spacing-0"><thead><tr><th class="bg-gray-500/20 px-3 py-2 text-left font-medium leading-snug border border-gray-500/20">Framework</th><th class="bg-gray-500/20 px-3 py-2 text-left font-medium leading-snug border border-gray-500/20">File pattern</th><th class="bg-gray-500/20 px-3 py-2 text-left font-medium leading-snug border border-gray-500/20">Ghi chú</th></tr></thead><tbody><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">**Jest**</td><td class="px-3 py-2 leading-snug border border-gray-500/20">`*.test.ts`, `*.spec.ts`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">Phổ biến nhất với React/Node</td></tr><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">**Vitest**</td><td class="px-3 py-2 leading-snug border border-gray-500/20">`*.test.ts`, `*.spec.ts`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">Nhanh hơn Jest, dành cho Vite</td></tr><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">**Playwright**</td><td class="px-3 py-2 leading-snug border border-gray-500/20">`e2e/*.spec.ts`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">E2E testing, browser automation</td></tr><tr><td class="px-3 py-2 leading-snug border border-gray-500/20">**pytest**</td><td class="px-3 py-2 leading-snug border border-gray-500/20">`test_*.py`, `*_test.py`</td><td class="px-3 py-2 leading-snug border border-gray-500/20">Python projects</td></tr></tbody></table>

</div>AI tự phát hiện framework đang dùng từ <span class="inline-flex break-all leading-tight">package.json</span> và tạo test theo đúng syntax.