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>
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
# 06. Hướng Dẫn Nâng Cao: PHP 8.4+ & Laravel 12 / 13 (Latest & Future-Proof)
|
||||
|
||||
Tài liệu này chuẩn bị đầy đủ các kỹ thuật kiểm thử cho các phiên bản PHP và Laravel mới nhất, bao gồm **PHP 8.4**, **Laravel 12 & 13**, **PHPUnit 11/12** và **Pest PHP v3**.
|
||||
|
||||
---
|
||||
|
||||
## 1. Kiểm Thử Các Tính Năng Mới Của PHP 8.4
|
||||
|
||||
PHP 8.4 giới thiệu nhiều thay đổi mang tính cách mạng trong cú pháp lập trình hướng đối tượng. Unit Test cần thích ứng chính xác:
|
||||
|
||||
### A. Property Hooks (`get` / `set`)
|
||||
Thay vì viết getter/setter truyền thống hoặc Eloquent Accessor cũ, PHP 8.4 cho phép định nghĩa hooks ngay trên thuộc tính:
|
||||
|
||||
```php
|
||||
// DTO hoặc Model trong PHP 8.4
|
||||
class UserProfile
|
||||
{
|
||||
public string $firstName;
|
||||
public string $lastName;
|
||||
|
||||
// Property Hook tự động tính toán
|
||||
public string $fullName {
|
||||
get => trim("{$this->firstName} {$this->lastName}");
|
||||
}
|
||||
|
||||
// Property Hook kiểm soát gán giá trị
|
||||
public string $email {
|
||||
set {
|
||||
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new \InvalidArgumentException('Email không hợp lệ');
|
||||
}
|
||||
$this->email = strtolower($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Cách viết Unit Test:
|
||||
```php
|
||||
#[Test]
|
||||
public function it_calculates_full_name_via_property_hook(): void
|
||||
{
|
||||
$profile = new UserProfile();
|
||||
$profile->firstName = 'Thien';
|
||||
$profile->lastName = 'Phan';
|
||||
|
||||
// Kiểm thử get hook
|
||||
$this->assertSame('Thien Phan', $profile->fullName);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_throws_exception_when_setting_invalid_email_hook(): void
|
||||
{
|
||||
$profile = new UserProfile();
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
// Kiểm thử set hook
|
||||
$profile->email = 'invalid-email-format';
|
||||
}
|
||||
```
|
||||
|
||||
### B. Asymmetric Visibility (`public private(set)`)
|
||||
PHP 8.4 cho phép thuộc tính có quyền đọc công khai nhưng chỉ được sửa từ bên trong class:
|
||||
|
||||
```php
|
||||
class BankAccount
|
||||
{
|
||||
// Đọc public từ ngoài, nhưng chỉ private method được set
|
||||
public private(set) int $balance = 0;
|
||||
|
||||
public function deposit(int $amount): void
|
||||
{
|
||||
if ($amount <= 0) {
|
||||
throw new \InvalidArgumentException('Số tiền nạp phải > 0');
|
||||
}
|
||||
$this->balance += $amount;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Cách viết Unit Test:
|
||||
```php
|
||||
#[Test]
|
||||
public function it_updates_balance_via_public_api_and_allows_public_reading(): void
|
||||
{
|
||||
$account = new BankAccount();
|
||||
|
||||
// Đọc trạng thái ban đầu
|
||||
$this->assertSame(0, $account->balance);
|
||||
|
||||
// Kích hoạt method hợp lệ
|
||||
$account->deposit(500_000);
|
||||
$this->assertSame(500_000, $account->balance);
|
||||
|
||||
// Cố tình ghi đè từ ngoài sẽ gây Error (PHP Fatal Error)
|
||||
// Unit test tập trung xác nhận method nội bộ thay đổi đúng giá trị
|
||||
}
|
||||
```
|
||||
|
||||
### C. Hàm Array Mới (`array_find`, `array_any`, `array_all`)
|
||||
Kiểm thử các business logic sử dụng các hàm tiện ích mảng mới của PHP 8.4.
|
||||
|
||||
---
|
||||
|
||||
## 2. Kiểm Thử Kiến Trúc Laravel Hiện Đại (Laravel 11, 12, 13)
|
||||
|
||||
### A. Concurrency API (`Concurrency::fake()`)
|
||||
Từ Laravel 11 và tiếp tục hoàn thiện trên Laravel 12/13, Laravel cung cấp Facade `Concurrency` để chạy các tác vụ song song:
|
||||
|
||||
```php
|
||||
// Trong Service
|
||||
public function fetchDashboardData(): array
|
||||
{
|
||||
return Concurrency::run([
|
||||
fn () => $this->userService->getStats(),
|
||||
fn () => $this->orderService->getRevenue(),
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
#### Cách viết Unit Test:
|
||||
```php
|
||||
use Illuminate\Support\Facades\Concurrency;
|
||||
|
||||
#[Test]
|
||||
public function it_executes_concurrent_tasks_correctly(): void
|
||||
{
|
||||
// Giả lập Concurrency để chạy tuần tự trong lúc test
|
||||
Concurrency::fake();
|
||||
|
||||
$dashboardData = $dashboardService->fetchDashboardData();
|
||||
|
||||
$this->assertCount(2, $dashboardData);
|
||||
}
|
||||
```
|
||||
|
||||
### B. Context API (`Context::fake()`)
|
||||
Laravel Context cho phép theo dõi metadata xuyên suốt vòng đời request và background jobs:
|
||||
|
||||
```php
|
||||
use Illuminate\Support\Facades\Context;
|
||||
|
||||
#[Test]
|
||||
public function it_attaches_trace_id_to_context(): void
|
||||
{
|
||||
$middleware = new TraceContextMiddleware();
|
||||
$request = Request::create('/api/orders', 'GET');
|
||||
$request->headers->set('X-Trace-ID', 'trace-xyz-123');
|
||||
|
||||
$middleware->handle($request, fn () => response('OK'));
|
||||
|
||||
$this->assertSame('trace-xyz-123', Context::get('trace_id'));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Pest PHP v3: Architecture Testing (`arch()`)
|
||||
|
||||
Trong các dự án Laravel 11/12/13 hiện đại dùng Pest v3, ngoài việc test từng method, chúng ta có thể viết **Architectural Tests** để kiểm soát toàn bộ cấu trúc code:
|
||||
|
||||
```php
|
||||
// tests/Unit/ArchitectureTest.php
|
||||
|
||||
describe('Architecture Rules', function () {
|
||||
test('Controllers do not directly use Models (must use Services/Actions)')
|
||||
->expect('App\Http\Controllers')
|
||||
->not->toUse('App\Models')
|
||||
->ignoring('App\Http\Controllers\Auth');
|
||||
|
||||
test('Services must be readonly or final')
|
||||
->expect('App\Services')
|
||||
->toBeFinal();
|
||||
|
||||
test('All Value Objects must be immutable')
|
||||
->expect('App\ValueObjects')
|
||||
->toBeReadonly();
|
||||
|
||||
test('No debugging functions left in code')
|
||||
->expect(['dd', 'dump', 'ray', 'var_dump'])
|
||||
->not->toBeUsed();
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Tương Thích PHPUnit 11 & 12
|
||||
|
||||
1. **Loại bỏ hoàn toàn DocBlock**: PHPUnit 11+ deprecate và loại bỏ chú thích dạng `@test`, `@dataProvider`. Bắt buộc 100% sử dụng:
|
||||
- `#[PHPUnit\Framework\Attributes\Test]`
|
||||
- `#[PHPUnit\Framework\Attributes\DataProvider('providerMethod')]`
|
||||
- `#[PHPUnit\Framework\Attributes\TestDox('Mô tả tiếng Việt dễ đọc')]`
|
||||
2. **Event-driven Internal System**: PHPUnit 11 quản lý vòng đời test hoàn toàn bằng sự kiện, giúp execution nhanh hơn và đo lường chính xác hơn.
|
||||
Reference in New Issue
Block a user