2045c856e9
- 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>
119 lines
4.2 KiB
Markdown
119 lines
4.2 KiB
Markdown
# 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/`:
|
|
|
|
```text
|
|
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()`:
|
|
```php
|
|
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`):
|
|
|
|
```php
|
|
#[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:
|
|
```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],
|
|
]);
|
|
```
|