Files
agent-unit-testing/docs/01-overview-and-principles.md
Pham-Tan-Thien 2045c856e9 feat: complete Smartgift AI Laravel unit testing toolkit
- Add 10 core testing guides (setup, AAA principles, PHPUnit/Pest, mocking, anti-patterns, PHP 8.4+, debugging, data factories, advanced edge cases)
- Add 13 component testing guides covering all Laravel layers
- Add standard templates for PHPUnit 10/11 and Pest v2/v3 including ArchitectureTest
- Add Docker smart test runner, dependency installer, and CI/CD templates (GitHub Actions, GitLab CI)
- Add 4 Claude Code skills (laravel-test-setup, laravel-unit-test with --all mode, laravel-test-review, laravel-mock-helper)
- Add single unified installer script (sg-install-unit-testing.sh) with global support, CLI runners, and 1-click updater (sg-test-update)
- Add comprehensive documentation (README.md, USAGE-GUIDE.md)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-07 16:41:37 +07:00

83 lines
4.7 KiB
Markdown

# 01. Overview & Core Principles of Laravel Unit Testing
Tài liệu này định nghĩa triết lý, nguyên tắc kiến trúc và tiêu chuẩn cốt lõi khi viết Unit Test cho mã nguồn Laravel.
---
## 1. Bản chất của Unit Test trong Laravel
### A. Định nghĩa Unit Test (Kiểm thử đơn vị)
- **Đối tượng**: Kiểm thử một Class duy nhất, một Method duy nhất, hoặc một đoạn Business Logic độc lập.
- **Phạm vi**: Hoàn toàn **cô lập (Isolated)**. Tất cả các thành phần ngoại vi (Database, Third-party API, File System, Queue, Mail, Event) đều phải được **giả lập (Mocked/Faked/Stubbed)**.
- **Tốc độ**: Cực nhanh (dưới 10ms - 50ms cho mỗi test case). Toàn bộ bộ Unit Test của một hệ thống lớn phải chạy xong trong vài giây.
### B. Ranh giới giữa Unit Test và Feature/Integration Test
Sự nhầm lẫn giữa Unit Test và Feature Test là nguyên nhân số 1 khiến test bị chậm và khó bảo trì:
| Tiêu chí | Unit Test | Feature / Integration Test |
| :--- | :--- | :--- |
| **Đối tượng test** | 1 Class / Method cụ thể (Service, Action, Value Object, Rule,...) | Toàn bộ luồng nghiệp vụ (Endpoint, Controller, Middleware, DB) |
| **Kế thừa TestCase** | `PHPUnit\Framework\TestCase` (thuần) hoặc `Tests\TestCase` (tối giản) | `Tests\TestCase` (boot toàn bộ Laravel Kernel) |
| **Database** | **KHÔNG DÙNG** Database thật (Mock repository/model) | Có dùng DB (thường dùng `RefreshDatabase` với SQLite/MySQL) |
| **HTTP Request** | Không dispatch HTTP request thật | Dùng `$this->getJson()`, `$this->postJson()` |
| **External Service** | Mock bằng Mockery hoặc Anonymous Stub | Fake bằng `Http::fake()`, `Event::fake()` |
| **Thời gian chạy** | Siêu nhanh (vài milliseconds) | Chậm hơn (vài chục đến hàng trăm milliseconds) |
> ⚠️ **Quy tắc vàng**: Nếu một test cần chạy migration, chèn dữ liệu vào bảng, gọi HTTP endpoint qua router -> Đó là **Feature Test**, KHÔNG PHẢI Unit Test.
---
## 2. Quy chuẩn Cấu trúc: Mô hình AAA (Arrange - Act - Assert)
Mọi bài test đơn vị đều phải tuân thủ nghiêm ngặt 3 giai đoạn:
```php
#[Test]
public function it_calculates_total_price_with_discount_successfully(): void
{
// 1. ARRANGE (Chuẩn bị dữ liệu đầu vào & thiết lập Mock)
$discountServiceMock = Mockery::mock(DiscountServiceInterface::class);
$discountServiceMock->shouldReceive('getPercentage')
->once()
->with('SUMMER2026')
->andReturn(20.0);
$cartService = new CartService($discountServiceMock);
$items = [
new CartItem(name: 'Item A', price: 100_000, quantity: 2), // 200,000
];
// 2. ACT (Thực thi hành động cần test)
$finalPrice = $cartService->calculateTotal($items, 'SUMMER2026');
// 3. ASSERT (Kiểm tra kết quả và xác thực side-effects)
$this->assertSame(160_000.0, $finalPrice);
}
```
- **Arrange**: Chuẩn bị đầy đủ input, khởi tạo đối tượng cần test, thiết lập kỳ vọng cho các dependency mock.
- **Act**: Gọi chính xác 1 method của đối tượng cần test. Không gọi lồng nhiều hành động.
- **Assert**: So sánh kết quả trả về với kỳ vọng; xác nhận mock method được gọi đúng số lần và đúng tham số.
---
## 3. Các Nguyên tắc Cốt lõi (Core Principles)
### 1. Nguyên tắc Đơn nhiệm (Single Concept per Test)
Mỗi test method chỉ kiểm tra **một khía cạnh duy nhất** của logic:
- 1 test cho trường hợp thành công (Happy path).
- 1 test cho trường hợp dữ liệu rỗng/null.
- 1 test cho trường hợp văng Exception khi đầu vào sai.
❌ Không gộp tất cả các kịch bản if/else vào chung một test method dài 100 dòng.
### 2. Tính Độc lập & Không Phụ thuộc Thứ tự (Independent & Isolated)
- Test case A chạy trước hay test case B chạy trước không được làm ảnh hưởng kết quả của nhau.
- Không chia sẻ trạng thái biến toàn cục (global state) hoặc static variable mà không dọn dẹp sau mỗi test (`tearDown()`).
### 3. Nguyên tắc FIRST trong Unit Testing
- **F - Fast**: Chạy trong chớp mắt.
- **I - Isolated / Independent**: Không phụ thuộc môi trường mạng, database bên ngoài.
- **R - Repeatable**: Chạy 100 lần trên máy local hay CI/CD đều cho ra kết quả giống nhau.
- **S - Self-validating**: Test tự xác nhận Pass hoặc Fail qua Assertions, không cần người đọc log để đoán.
- **T - Thorough / Timely**: Bao phủ từ Happy Path cho đến các trường hợp biên khắc nghiệt (Edge cases).