Files
agent-unit-testing/docs/04-naming-and-structure.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.2 KiB

04. Naming Conventions & Test Structure

Quy chuẩn đặt tên, ánh xạ thư mục và tổ chức mã nguồn kiểm thử trong Laravel để đảm bảo tính nhất quán và rõ ràng cho cả lập trình viên lẫn công cụ CI/CD.


1. Ánh xạ Cấu trúc Thư mục (Directory Mapping)

Cấu trúc thư mục của file Test trong tests/Unit/ phải phản chiếu 1-1 (Mirror) cấu trúc của class nguồn trong app/:

app/
├── Actions/
│   └── User/
│       └── CreateUserAction.php
├── Services/
│   └── Payment/
│       └── StripePaymentService.php
├── Rules/
│   └── ValidTaxCodeRule.php
└── Jobs/
    └── ProcessPodcastJob.php

tests/
└── Unit/
    ├── Actions/
    │   └── User/
    │       └── CreateUserActionTest.php
    ├── Services/
    │   └── Payment/
    │       └── StripePaymentServiceTest.php
    ├── Rules/
    │   └── ValidTaxCodeRuleTest.php
    └── Jobs/
        └── ProcessPodcastJobTest.php

2. Quy ước Đặt tên File & Class Test

  • Quy tắc: Tên file test = <TênClassNguồn>Test.php.
  • Namespace: Tương ứng theo namespace của class nguồn nhưng bắt đầu bằng Tests\Unit\....
  • Ví dụ:
    • Class nguồn: App\Services\InvoiceService
    • Class test: Tests\Unit\Services\InvoiceServiceTest

3. Quy ước Đặt tên Phương thức Test (Test Method Naming)

Mỗi tên method test phải đọc như một câu hoàn chỉnh, thể hiện rõ Hành vi (Action) và Kết quả kỳ vọng (Expected Outcome) trong một Điều kiện cụ thể (Context).

Cú pháp chuẩn PHPUnit:

Dùng định dạng snake_case bắt đầu bằng test_it_... hoặc it_... (nếu có attribute #[Test]):

  1. Happy Path (Thành công):
    • it_creates_order_and_dispatches_event_when_inventory_is_available()
    • it_returns_discounted_amount_for_vip_customer()
  2. Failure / Edge Case (Thất bại / Biên):
    • it_throws_out_of_stock_exception_when_inventory_is_zero()
    • it_fails_validation_when_email_domain_is_blacklisted()
  3. Authorization (Phân quyền):
    • it_denies_access_when_user_is_not_admin()

Cú pháp chuẩn Pest PHP:

Dùng chuỗi mô tả tự nhiên trong hàm it() hoặc test():

describe('InvoiceService', function () {
    it('creates invoice and dispatches event when payment succeeds', function () { ... });
    it('throws insufficient funds exception when balance is too low', function () { ... });
    it('denies access when user is not admin', function () { ... });
});

4. Tổ chức Data Providers

Khi một method cần test với nhiều bộ dữ liệu (Input -> Output) khác nhau:

Quy tắc PHPUnit:

  • Đặt tên provider: <tên_logic_test>_provider hoặc provide_<tên_logic_test>.
  • Khai báo là public static function.
  • Luôn đặt Key dạng chuỗi có ý nghĩa cho từng data set (để khi test fail, CLI báo rõ data set nào bị hỏng thay vì chỉ báo index số 0, 1, 2):
#[Test]
#[DataProvider('emailValidationProvider')]
public function it_validates_email_format(string $email, bool $expectedResult): void
{
    $validator = new EmailValidator();
    $this->assertSame($expectedResult, $validator->isValid($email));
}

public static function emailValidationProvider(): array
{
    return [
        'standard email'            => ['user@example.com', true],
        'email with sub-domain'     => ['user@corp.example.co.uk', true],
        'missing at symbol'         => ['userexample.com', false],
        'missing domain'            => ['user@', false],
        'whitespace in email'       => ['user @example.com', false],
    ];
}

Quy tắc Pest PHP:

it('validates email format', function (string $email, bool $expectedResult) {
    $validator = new EmailValidator();
    expect($validator->isValid($email))->toBe($expectedResult);
})->with([
    'standard email'        => ['user@example.com', true],
    'email with sub-domain' => ['user@corp.example.co.uk', true],
    'missing at symbol'     => ['userexample.com', false],
]);