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

4.7 KiB

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:

#[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).