feat: add comprehensive unit testing support for CakePHP

- Add 4 CakePHP Claude Code skills: cakephp-unit-test, cakephp-test-setup, cakephp-test-review, cakephp-mock-helper
- Add 11 CakePHP PHPUnit component templates (Table, Entity, Controller, Service, Command, Component, Middleware, Mailer, Form, Behavior, Helper)
- Add CakePHP configs (phpunit.xml.dist, app_local.test.php for SQLite in-memory)
- Add comprehensive CakePHP documentation and component guides
- Update test-runner.sh and installer to auto-detect Laravel and CakePHP
- Add CakePHP CI/CD templates for GitHub Actions and GitLab CI
- Update system prompt, verification checklist, and README with dedicated guides
This commit is contained in:
2026-09-14 10:19:40 +07:00
parent 0dce2ef812
commit 7425b263d5
28 changed files with 2210 additions and 356 deletions
@@ -0,0 +1,54 @@
---
name: cakephp-mock-helper
description: Phân tích một Class, Interface hoặc Table CakePHP và tự động sinh khối mã thiết lập Mock (PHPUnit Mock Double / Mockery) chuẩn cú pháp.
---
# Skill: CakePHP Mock Helper
Skill này hỗ trợ lập trình viên sinh nhanh mã giả lập (Mocking code) cho một CakePHP Component, Table, Service hoặc External Client.
## Cách kích hoạt
```text
/cakephp-mock-helper <tên_class_hoặc_đường_dẫn>
```
*Ví dụ*: `/cakephp-mock-helper App\Service\PaymentGatewayService`
*Ví dụ*: `/cakephp-mock-helper App\Controller\Component\StripeComponent`
---
## Quy trình xử lý của Agent:
1. Đọc nội dung file class/interface được cung cấp.
2. Liệt kê toàn bộ các `public methods`, tham số và kiểu trả về.
3. Sinh ra 2 phiên bản mã Mock:
- **Phiên bản PHPUnit Native Mock** (`$this->createMock(...)` hoặc `$this->getMockBuilder(...)`).
- **Phiên bản Mockery** (`Mockery::mock(...)`).
4. Kèm theo cả Happy Path (trả về kết quả hợp lệ) và Failure/Exception case.
## Mẫu kết quả trả về:
```php
// ==========================================
// 1. DÙNG PHPUNIT NATIVE MOCK (Khuyên dùng cho CakePHP)
// ==========================================
$serviceMock = $this->createMock(\App\Service\PaymentGatewayService::class);
// Kịch bản Happy Path:
$serviceMock->expects($this->once())
->method('charge')
->with(150.00, 'USD')
->willReturn(['status' => 'success', 'transaction_id' => 'TXN_999']);
// Kịch bản Exception:
$serviceMock->expects($this->once())
->method('charge')
->willThrowException(new \RuntimeException('Payment gateway timeout'));
// ==========================================
// 2. DÙNG MOCKERY (Nếu dự án có cài Mockery)
// ==========================================
$serviceMock = Mockery::mock(\App\Service\PaymentGatewayService::class);
$serviceMock->shouldReceive('charge')
->once()
->with(150.00, 'USD')
->andReturn(['status' => 'success', 'transaction_id' => 'TXN_999']);
```
@@ -0,0 +1,65 @@
---
name: cakephp-test-review
description: Đánh giá, chấm điểm chất lượng và phát hiện các lỗi anti-patterns trong file Unit / Integration Test CakePHP có sẵn theo thang điểm 100.
---
# Skill: CakePHP Test Reviewer
Skill này chịu trách nhiệm kiểm tra chất lượng và phát hiện lỗi anti-patterns trong một file test CakePHP đã viết sẵn.
## Cách kích hoạt
```text
/cakephp-test-review <đường_dẫn_file_test>
```
*Ví dụ*: `/cakephp-test-review tests/TestCase/Model/Table/ArticlesTableTest.php`
*Ví dụ*: `/cakephp-test-review tests/TestCase/Controller/ArticlesControllerTest.php`
---
## Tiêu Chí Đánh Giá (Scoring Criteria - Thang Điểm 100)
Agent sẽ quét file test qua 5 tiêu chí chuẩn:
### 1. Tính Cô Lập & An Toàn Dữ Liệu (Isolation & Database Safety - 25đ)
- Test có dùng đúng test datasource (`Datasources.test`) hoặc fixtures không, hay vô tình tác động lên database dev thật?
- Có bị gọi HTTP ra API ngoài thực tế mà quên mock không?
- Fixture có được khai báo tối giản chỉ những bảng cần thiết (tránh nạp thừa hàng chục bảng gây chậm)?
### 2. Sử Dụng Đúng Trait & Chuẩn CakePHP (CakePHP Conventions - 20đ)
- Controller test có dùng `Cake\TestSuite\IntegrationTestTrait` không (hay tạo `new Controller` thủ công - Anti-pattern)?
- Command test có dùng `Cake\Console\TestSuite\ConsoleIntegrationTestTrait` không?
- Mailer test có dùng `Cake\TestSuite\EmailTrait` không?
- Có bật `enableCsrfToken()` và `enableSecurityToken()` khi test POST/PUT không?
### 3. Chiến Lược Giả Lập & Fixtures (Mocking vs Fixtures - 20đ)
- Có bị over-mocking (Mock cả Entity, Table query cơ bản thay vì dùng Fixture) không?
- Các service bên thứ 3 (Payment, Notification, Cloud Storage) có được mock rõ ràng với số lần gọi (`->once()`, `->never()`) không?
### 4. Cấu Trúc & Assertions (Structure & Assertions - 20đ)
- Có tuân thủ mô hình **AAA** (`// Arrange`, `// Act`, `// Assert`) rõ ràng không?
- Dùng assertion đặc thù của CakePHP: `$this->assertResponseOk()`, `$this->assertResponseCode(200)`, `$this->assertRedirect()`, `$this->assertFlashMessage()` thay vì assert thủ công yếu ớt?
- Dùng strict assertions: `$this->assertSame()` thay vì `$this->assertEquals()`.
### 5. Độ Phủ Kịch Bản & Nhánh Biên (Scenario & Branch Coverage - 15đ)
- Đã kiểm tra cả Happy Path lẫn Unhappy Path (validation lỗi, entity không tìm thấy 404, không có quyền 403)?
- Các giá trị biên (`null`, mảng rỗng, chuỗi trắng) đã được kiểm thử đầy đủ chưa?
---
## Báo Cáo Đầu Ra Mẫu:
```markdown
### 🔍 BÁO CÁO REVIEW TEST CAKEPHP: `ArticlesControllerTest.php`
**Điểm tổng kết: 65/100 (Cần cải thiện)**
#### ⚠️ Các vấn đề phát hiện (Anti-Patterns):
1. **Thiếu CSRF/Security Token tại line 32**: Gọi POST `/articles/add` nhưng chưa kích hoạt `$this->enableCsrfToken()`, dễ dẫn đến test fail khi bật middleware CSRF.
2. **Assertion lỏng lẻo tại line 45**: Dùng `$this->assertTrue(true)` thay vì `$this->assertResponseSuccess()` hoặc kiểm tra dữ liệu thật được lưu vào DB.
3. **Chưa có kịch bản Validation Failure**: Chưa kiểm thử trường hợp người dùng submit form thiếu trường `title` bắt buộc.
#### 💡 Đề xuất Refactor:
```php
// Đoạn code được sửa lại chuẩn AAA và tận dụng đầy đủ IntegrationTestTrait...
```
```
+109
View File
@@ -0,0 +1,109 @@
---
name: cakephp-test-setup
description: Tự động quét kiểm tra môi trường, dependencies, database config (Datasources.test) và docker để chuẩn bị viết Unit Test cho bất kỳ dự án CakePHP nào.
---
# Skill: CakePHP Test Environment Setup & Health Check
Skill này chịu trách nhiệm chuẩn bị "Bước 0" cho dự án CakePHP trước khi bắt đầu viết bất kỳ Unit/Integration Test nào.
## Cách kích hoạt
- **Chế độ kiểm tra (Dry-run / Health-Check)**:
```text
/cakephp-test-setup
```
- **Chế độ tự động cài đặt gói thiếu (Auto-Install Mode)**:
```text
/cakephp-test-setup --install
```
## Quy trình thực hiện (Execution Workflow)
Khi người dùng kích hoạt lệnh `/cakephp-test-setup`, Agent sẽ tuần tự thực hiện các bước sau:
### Bước 1: Quét `composer.json` & Nhận Diện CakePHP Version
1. Đọc file `composer.json` tại thư mục gốc của dự án.
2. Xác định:
- **Phiên bản CakePHP**:
- `cakephp/cakephp: ^5.0`: Yêu cầu PHP >= 8.1
- `cakephp/cakephp: ^4.0`: Yêu cầu PHP >= 7.4
- `cakephp/cakephp: ^3.0`: Legacy CakePHP 3.x
- **Test Runner & Dependencies**:
- `phpunit/phpunit`
- `cakephp/cakephp-codesniffer` (nếu có)
- `mockery/mockery` (hỗ trợ nâng cao)
- `fakerphp/faker`
3. Nếu phát hiện thiếu thư viện hoặc cờ `--install`:
- Kích hoạt lệnh cài đặt qua môi trường tương ứng:
```bash
# Nếu dùng Docker Compose (service app / web / php):
docker compose exec -T app composer require --dev mockery/mockery fakerphp/faker --with-all-dependencies
# Nếu chạy Local:
composer require --dev mockery/mockery fakerphp/faker --with-all-dependencies
```
### Bước 2: Kiểm tra Cấu hình Testing Database (`Datasources.test`)
1. Kiểm tra file `config/app_local.php` hoặc `config/app.php`.
2. Xác thực cấu hình `Datasources.test`:
- Đảm bảo kết nối `test` được tách biệt với `default` (production/dev).
- Khuyên dùng SQLite In-Memory hoặc SQLite file test để đảm bảo **tốc độ cao và an toàn tuyệt đối 100% cho dữ liệu dev**:
```php
'test' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Sqlite',
'database' => ':memory:', // hoặc TMP . 'test.sqlite'
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
],
```
3. Kiểm tra file cấu hình PHPUnit (`phpunit.xml` hoặc `phpunit.xml.dist`):
- Đảm bảo có suite `<testsuite name="app">` trỏ vào `tests/TestCase`.
- Có extension / listener fixture (`Cake\TestSuite\Fixture\FixtureExtension` cho CakePHP 4.3+ / 5.x).
### Bước 3: Phát hiện Môi trường Docker / Runtime
1. Kiểm tra `bin/cake` -> Đảm bảo có quyền thực thi (`chmod +x bin/cake`).
2. Kiểm tra `docker-compose.yml` -> Dò tìm service chạy CakePHP (`app`, `web`, `php`, `backend`) -> Lệnh chuẩn:
```bash
docker compose exec -T app bin/cake test app
# Hoặc:
docker compose exec -T app vendor/bin/phpunit
```
3. Nếu chạy Local: Kiểm tra PHP CLI có đủ extension `intl` (`php -m | grep intl`) và `pdo_sqlite` (`php -m | grep sqlite`).
### Bước 4: Chạy Smoke Test (Kiểm tra thử nghiệm)
1. Chạy thử nghiệm một test case mẫu sẵn có hoặc test mặc định:
```bash
./test-runner.sh
# hoặc bin/cake test app
```
2. Nếu test PASS: Báo cáo môi trường đã sẵn sàng 100%.
3. Nếu test FAIL: Đưa ra chẩn đoán chính xác nguyên nhân (thiếu driver SQLite, sai database credentials, thiếu fixture strategy,...).
---
## Mẫu báo cáo đầu ra cho người dùng:
```markdown
### 📋 BÁO CÁO MÔI TRƯỜNG TEST CAKEPHP (HEALTH CHECK)
1. **Framework & Dependencies**:
- CakePHP: 4.5.3 (hoặc 5.0.x) | PHP: 8.2
- Test Runner: PHPUnit 10.5
- Mocking: Mockery 1.6 (Đã cài)
- Fixture Strategy: TransactionStrategy / FixtureExtension [OK]
2. **Cấu hình Môi trường Test**:
- Datasource Test: SQLite (:memory:) [OK - An toàn, không đụng dữ liệu dev]
- phpunit.xml: Đã cấu hình suite `app` trỏ tới `tests/TestCase`
3. **Môi trường thực thi**:
- Docker Service: `app` (hoặc `web`) đang hoạt động
- Lệnh chạy test chuẩn: `docker compose exec -T app bin/cake test app`
4. **Kết quả Smoke Test**:
- Trạng thái: ✅ PASSED
🎉 **Môi trường CakePHP đã hoàn toàn sẵn sàng cho việc sinh Unit Test!**
```
+138
View File
@@ -0,0 +1,138 @@
---
name: cakephp-unit-test
description: Phân tích một class mã nguồn PHP CakePHP (Table, Entity, Controller, Service, Command, Component, Middleware, Mailer, Form, Behavior) và tự động sinh file Unit / Integration Test hoàn chỉnh đạt chuẩn AAA, cô lập cao và bao phủ biên.
---
# Skill: CakePHP Unit & Integration Test Generator
Skill này là công cụ chính để tự động tạo ra file Test cho bất kỳ class nào trong dự án CakePHP (từ CakePHP 3.x, 4.x đến 5.x+).
## Cách kích hoạt
### 🏆 QUY TRÌNH CHUẨN PRO CHO DỰ ÁN LỚN (KHUYÊN DÙNG NHẤT):
Để tránh bị tràn context token và đảm bảo viết sâu 100% từng nhánh SonarQube, hãy tách biệt 2 pha: **PHA VIẾT (Generation)** và **PHA CHẠY (Execution)**:
1. **Bước 1: Quét bản đồ dự án (`--untested`)**:
```text
/cakephp-unit-test --untested
```
*Liệt kê danh sách class trong `src/` chưa có test trong `tests/TestCase/` theo độ ưu tiên: Tables/Entities -> Services -> Controllers -> Commands -> Components/Middlewares.*
2. **Bước 2: Viết test tập trung theo từng tầng (CHỈ VIẾT, CHƯA CHẠY TEST)**:
```text
/cakephp-unit-test src/Model/Table/
# Sau khi xong, viết tiếp:
/cakephp-unit-test src/Service/
/cakephp-unit-test src/Controller/
/cakephp-unit-test src/Command/
```
*AI dồn 100% token tập trung sinh test sâu, đầy đủ Happy Path, Edge Cases, Exception và Branch Coverage.*
3. **Bước 3: Chạy test đồng loạt ngoài Terminal & Nghiệm thu**:
```bash
./test-runner.sh --coverage
```
*Chạy 1 lần duy nhất bằng `bin/cake test app` hoặc `phpunit` trên In-memory SQLite siêu tốc, đo độ phủ và xuất file báo cáo.*
---
### ⚡ CÁC CHẾ ĐỘ TIỆN ÍCH KHÁC:
4. **Chế độ Autopilot Khép Kín: Viết & Chạy Test Ngay (`--all --run` hoặc `--autopilot`)**:
```text
/cakephp-unit-test --all --run
```
*Dành cho dự án vừa và nhỏ: AI tự lập manifest, viết đến đâu chạy `./test-runner.sh` ngay đến đó, tự động sửa lỗi (Auto-Healing) nếu test fail.*
5. **Chế độ Viết Cho 1 File & Test Luôn (`--run`)**:
```text
/cakephp-unit-test src/Model/Table/UsersTable.php --run
```
6. **Chế độ Theo Git Diff (Dành Cho Pull Request)**:
```text
/cakephp-unit-test --changed
```
7. **Chế độ File đơn lẻ**:
```text
/cakephp-unit-test src/Controller/ArticlesController.php
```
---
## Quy trình 6 Bước Tự Động của Agent
### Bước 1: Khảo sát Môi trường & Phiên bản CakePHP
1. Đọc `composer.json` để xác định:
- **Phiên bản CakePHP**:
- CakePHP 5.x: PHP >= 8.1, kiểu khai báo kiểu nghiêm ngặt (strict types), Attributes PHP 8 `#[Test]`.
- CakePHP 4.x: PHP 7.4 - 8.2, `Cake\TestSuite\TestCase`, dùng `fetchTable()`.
- CakePHP 3.x: `TableRegistry::get()`.
- **PHPUnit**: PHPUnit 9 / 10 / 11.
### Bước 2: Phân tích File Nguồn & Xác Định Loại Component
1. Đọc toàn bộ nội dung file class nguồn được chỉ định.
2. Xác định cấu trúc Component CakePHP:
- **Table (`src/Model/Table/*Table.php`)**: Test validation rules, custom finder methods (`findTagged()`, `findAuth()`), buildRules, save/delete logic.
- **Entity (`src/Model/Entity/*.php`)**: Test virtual fields, mutators (`_setPassword()`), accessors, hidden/accessible properties.
- **Controller (`src/Controller/*Controller.php`)**: Dùng `Cake\TestSuite\IntegrationTestTrait`. Test endpoints HTTP (GET, POST, PUT, DELETE), flash messages, redirect, view vars, auth/session.
- **Service / Action (`src/Service/*.php`)**: Test logic nghiệp vụ thuần túy, mock các dependency ngoài hoặc Table locator.
- **Command (`src/Command/*Command.php`)**: Dùng `Cake\Console\TestSuite\ConsoleIntegrationTestTrait`. Test arguments, options, output text, exit code (`CODE_SUCCESS`, `CODE_ERROR`).
- **Component (`src/Controller/Component/*.php`)**: Test logic tái sử dụng của Controller với mocked Controller/Request/Response.
- **Middleware (`src/Middleware/*.php`)**: Test PSR-15 / CakePHP middleware với `ServerRequest` và `ResponseHandler`.
- **Mailer (`src/Mailer/*Mailer.php`)**: Dùng `Cake\TestSuite\EmailTrait`. Test subject, to, template, view vars.
- **Form (`src/Form/*Form.php`)**: Test `validationDefault()`, `_buildSchema()`, `_execute()`.
- **Behavior (`src/Model/Behavior/*.php`)**: Test ORM hooks (`beforeSave`, `beforeFind`,...).
- **Helper (`src/View/Helper/*.php`)**: Test render HTML, tags, view outputs.
### Bước 3: Xác Định Fixtures & Chiến Lược Giả Lập (Mocking)
- **Database & Fixtures**:
- Đối với Table & Controller test: Xác định các bảng liên quan để khai báo fixture:
```php
protected array $fixtures = [
'app.Users',
'app.Articles',
];
```
- **External Dependencies & APIs**:
- Dùng Mockery hoặc PHPUnit Mock (`$this->createMock()`) cho các HTTP Client ngoài, 3rd party SDKs, Payment Gateway.
- **Session & Auth**:
- Đối với Controller: `$this->session(['Auth.User.id' => 1])` hoặc Token-based Auth.
- Kích hoạt CSRF & Security token khi test POST:
```php
$this->enableCsrfToken();
$this->enableSecurityToken();
```
### Bước 4: Lập Ma Trận Test Scenarios (Bao Phủ 100% Nhánh SonarQube)
- **100% Public Methods**: Mọi phương thức public đều phải có test.
- Với Table: bắt buộc test custom finders, validation failures, save thành công & thất bại.
- Với Controller: bắt buộc test thành công (200/302), validation failure (422/render form), unauthorized (403/redirect login), not found (404).
- Với Command: bắt buộc test `execute()` với input đúng, input thiếu, exit code.
- **Bao phủ nhánh rẽ**:
- Kịch bản Null Coalescing `??` và Ternary `?:`.
- Kịch bản `try - catch`: ép mock/dữ liệu ném Exception để chạy qua khối `catch`.
- Mọi `if`, `else if`, `else`, `switch`, `match`.
### Bước 5: Sinh Mã Nguồn Test Chuẩn Mirror
1. Xác định đường dẫn file test theo chuẩn CakePHP:
- Nguồn: `src/Model/Table/ArticlesTable.php`
- Đích: `tests/TestCase/Model/Table/ArticlesTableTest.php`
- Nguồn: `src/Controller/ArticlesController.php`
- Đích: `tests/TestCase/Controller/ArticlesControllerTest.php`
- Nguồn: `src/Command/CleanCacheCommand.php`
- Đích: `tests/TestCase/Command/CleanCacheCommandTest.php`
2. Sử dụng đúng base class:
- `Cake\TestSuite\TestCase` (kèm các Trait tương ứng: `IntegrationTestTrait`, `ConsoleIntegrationTestTrait`, `EmailTrait`).
3. Viết code theo mô hình **AAA** (`// Arrange`, `// Act`, `// Assert`).
### Bước 6: Thẩm định & Lưu File
1. Tự kiểm tra file test qua checklist quy chuẩn.
2. Ghi file test vào thư mục `tests/TestCase/...`.
3. In ra lệnh chạy test gợi ý:
```bash
bin/cake test app tests/TestCase/Model/Table/ArticlesTableTest.php
# Hoặc:
./test-runner.sh --filter=ArticlesTableTest
```