feat: decouple Laravel and CakePHP installers, remove SonarQube artifacts, and enforce complete unit testing standards

- Decouple framework installation: add install-laravel.sh and install-cakephp.sh, isolate skills and docs per framework, and auto-clean leftover artifacts
- Remove all SonarQube configs, templates, and references
- Enforce comprehensive test completeness: 100% public methods, edge cases, full branch coverage, exception paths, and state assertions
- Replace all placeholder assertions in PHPUnit and Pest templates with full realistic implementations
- Rename and update 10-comprehensive-test-coverage-guide.md
This commit is contained in:
2026-09-17 14:25:02 +07:00
parent 97f3833bf2
commit da1bd48444
33 changed files with 1004 additions and 594 deletions
+27 -11
View File
@@ -1,6 +1,6 @@
# Ma Trận Kịch Bản Biên & Ngoại Lệ (Edge Cases Matrix)
# Ma Trận Kịch Bản Biên & Ngoại Lệ (Edge Cases & Boundary Matrix)
Bảng phân loại toàn diện các tình huống biên cần phải kiểm thử đối với từng kiểu dữ liệu và nghiệp vụ trong ứng dụng Laravel.
Bảng phân loại toàn diện các tình huống biên bắt buộc phải kiểm thử đối với từng kiểu dữ liệu, cấu trúc điều khiển và nghiệp vụ trong ứng dụng **Laravel & CakePHP** để đảm bảo file test được viết **đầy đủ 100% không bỏ sót bất kỳ kịch bản nào**.
---
@@ -8,20 +8,36 @@ Bảng phân loại toàn diện các tình huống biên cần phải kiểm th
| Loại dữ liệu | Kịch bản biên bắt buộc phải test |
| :--- | :--- |
| **String (Chuỗi)** | - Chuỗi rỗng: `""`<br>- Chuỗi chỉ chứa khoảng trắng: `" "`<br>- Chuỗi cực dài vượt giới hạn database/API (e.g. > 255 ký tự hoặc > 65535 ký tự)<br>- Chuỗi chứa ký tự Unicode đặc biệt / Emoji: `"Nguyễn Văn A 🚀 🔥"`<br>- Chuỗi chứa mã độc hại: `<script>alert(1)</script>` hoặc SQL injection test |
| **Number (Số)** | - Số `0`<br>- Số âm: `-1`, `-99999`<br>- Số thực với số thập phân dài: `0.00000001`<br>- Giá trị cực đại (PHP_INT_MAX)<br>- Phép chia cho `0` (Division by zero) |
| **Array (Mảng)** | - Mảng rỗng: `[]`<br>- Mảng thiếu các key bắt buộc<br>- Mảng chứa giá trị `null` ở các field quan trọng<br>- Mảng lồng nhau nhiều cấp (Deeply nested)<br>- Mảng có key trùng lặp hoặc không tuần tự |
| **String (Chuỗi)** | - Chuỗi rỗng: `""`<br>- Chuỗi chỉ chứa khoảng trắng: `" "`<br>- Chuỗi cực dài vượt giới hạn database/API (e.g. > 255 ký tự hoặc > 65535 ký tự)<br>- Chuỗi chứa ký tự Unicode đặc biệt / Emoji: `"Nguyễn Văn A 🚀 🔥"`<br>- Chuỗi chứa mã HTML độc hại hoặc ký tự đặc biệt: `<script>alert(1)</script>`, `O'Connor`, `' OR '1'='1` |
| **Number (Số)** | - Số `0`<br>- Số âm: `-1`, `-99999`<br>- Số thực với số thập phân dài: `0.00000001`<br>- Giá trị cực đại (`PHP_INT_MAX`), giá trị cực tiểu (`PHP_INT_MIN`)<br>- Phép chia cho `0` (Division by zero) |
| **Array (Mảng / Collection)** | - Mảng rỗng: `[]`<br>- Mảng 1 phần tử (single element) vs Nhiều phần tử<br>- Mảng thiếu các key bắt buộc<br>- Mảng chứa giá trị `null` ở các field quan trọng<br>- Mảng lồng nhau nhiều cấp (Deeply nested)<br>- Mảng có key không tuần tự hoặc trùng lặp |
| **Boolean** | - Bắt buộc kiểm thử cả 2 giá trị `true` và `false` cho mọi cờ logic, permissions và options |
| **Date / Time (Thời gian)** | - Thời gian quá khứ vs Hiện tại vs Tương lai<br>- Ngày nhuận (29/02)<br>- Chuyển giao năm cũ sang năm mới (31/12 -> 01/01)<br>- Khác biệt múi giờ (Timezone discrepancies: UTC vs Local) |
| **Object / Model** | - Object bị `null`<br>- Model không tồn tại ID tương ứng<br>- Model ở trạng thái Soft-Deleted<br>- Model thiếu quan hệ (Missing relationship / Relation not loaded) |
| **Object / Entity / Model** | - Object bị `null`<br>- Model không tìm thấy trong Database (`ModelNotFoundException`, `RecordNotFoundException`)<br>- Model ở trạng thái Soft-Deleted<br>- Model thiếu quan hệ (Missing relationship / Relation not loaded) |
---
## 2. Phân Loại Nghiệp Vụ & Dịch Vụ Ngoài (Business & External Services)
## 2. Phân Loại Cấu Trúc Điều Khiển & Nhánh Rẽ (Branching & Control Flow)
| Cấu trúc điều khiển | Yêu cầu kịch bản test bắt buộc |
| :--- | :--- |
| **Null Coalescing (`??`)** | Bắt buộc 2 test cases: (1) Biến bên trái có giá trị -> Lấy giá trị đó; (2) Biến bên trái là `null` hoặc key không tồn tại -> Lấy giá trị fallback bên phải. |
| **Toán tử Ternary (`?:`)** | Bắt buộc 2 test cases: (1) Biểu thức đánh giá là `true` -> Trả về vế 1; (2) Biểu thức đánh giá là `false` -> Trả về vế 2. |
| **Biểu thức Logic `&&`** | Bắt buộc test: (1) Tất cả vế đều `true` -> Pass; (2) Vế đầu `false` -> Short-circuit; (3) Vế đầu `true`, vế sau `false` -> Fail. |
| **Biểu thức Logic `\|\|`** | Bắt buộc test: (1) Vế đầu `true` -> Short-circuit; (2) Vế đầu `false`, vế sau `true` -> Pass; (3) Cả hai vế đều `false` -> Fail. |
| **`try - catch - finally`** | (1) Kịch bản bình thường chạy trọn vẹn `try`; (2) Ép mock ném Exception để kích hoạt toàn bộ thân khối `catch` (xác minh ghi log lỗi, rollback transaction, trả fallback hoặc re-throw). |
| **`switch` / `match`** | Mỗi nhánh `case` / arm bắt buộc có ít nhất 1 test case; Nhánh `default` (hoặc ngoại lệ unhandled) bắt buộc phải có test case kích hoạt. |
| **Early Returns / Guard Clauses** | Mỗi guard clause kiểm tra điều kiện thoát sớm (ví dụ: `if (!$valid) return false;`) bắt buộc có 1 test case kích hoạt thoát sớm. |
---
## 3. Phân Loại Nghiệp Vụ & Dịch Vụ Ngoài (Business & External Services)
| Nhóm nghiệp vụ | Tình huống cần test |
| :--- | :--- |
| **Authentication & Authorization** | - Người dùng chưa đăng nhập (Unauthenticated / Guest / `null`)<br>- Người dùng đã đăng nhập nhưng không đủ quyền (Unauthorized / 403)<br>- Người dùng bị khóa tài khoản (Inactive / Banned)<br>- Token hết hạn hoặc không hợp lệ |
| **HTTP Client / External API** | - API phản hồi thành công (200, 201)<br>- API trả về lỗi nghiệp vụ (400 Bad Request, 422 Unprocessable)<br>- API từ chối xác thực (401, 403)<br>- API bị sập (500, 502, 503)<br>- API bị treo kết nối (Network Timeout / SocketException)<br>- API trả về cấu trúc JSON sai định dạng (Malformed JSON) |
| **Authentication & Authorization** | - Người dùng chưa đăng nhập (Unauthenticated / Guest / `null`) -> 401 hoặc Redirect Login<br>- Người dùng đã đăng nhập nhưng không đủ quyền (Unauthorized) -> 403 Forbidden<br>- Người dùng bị khóa tài khoản (Inactive / Banned)<br>- Token hết hạn hoặc không hợp lệ |
| **HTTP Client / External API** | - API phản hồi thành công (200, 201)<br>- API trả về lỗi nghiệp vụ (400 Bad Request, 422 Unprocessable Entity)<br>- API từ chối xác thực (401, 403)<br>- API bị sập (500, 502, 503)<br>- API bị treo kết nối (Network Timeout / SocketException)<br>- API trả về cấu trúc JSON sai định dạng (Malformed JSON) |
| **Database & Transactions** | - Thêm/sửa/xóa thành công -> Dữ liệu thật được lưu (`assertDatabaseHas`)<br>- Lỗi phát sinh trong transaction -> Dữ liệu được rollback hoàn toàn (`assertDatabaseMissing`)<br>- Vi phạm ràng buộc toàn vẹn: khóa ngoại không tồn tại, trùng khóa duy nhất (`unique`) |
| **Storage & File Upload** | - File rỗng (0 bytes)<br>- Dung lượng file vượt quá giới hạn (Max upload size exceeded)<br>- Định dạng đuôi file không được phép (MIME type mismatch)<br>- Đĩa lưu trữ bị đầy hoặc không có quyền ghi |
| **Queue & Background Jobs** | - Job thực thi thành công<br>- Job bị fail ở lần thử đầu tiên và kích hoạt retry<br>- Job bị fail hoàn toàn (hết số lần retry) -> kích hoạt hàm `failed()`<br>- Job nhận payload bị thiếu hoặc serialized object đã bị xóa |
| **Concurrency & Race Conditions**| - Hai yêu cầu cùng trừ tiền hoặc cùng đặt mua một sản phẩm còn 1 số lượng<br>- Idempotency: Gửi lại cùng một transaction ID 2 lần |
| **Queue & Background Jobs** | - Job thực thi thành công phương thức `handle()`<br>- Job bị fail ở lần thử đầu tiên và kích hoạt retry<br>- Job bị fail hoàn toàn (hết số lần retry) -> kích hoạt phương thức `failed(Throwable $e)`<br>- Job nhận payload bị thiếu hoặc serialized model đã bị xóa |
| **Concurrency & Idempotency** | - Hai yêu cầu cùng thao tác tài nguyên (ví dụ trừ tiền hoặc giảm tồn kho)<br>- Idempotency: Gửi lại cùng một request/token 2 lần không gây trùng lặp giao dịch |
+56 -29
View File
@@ -1,51 +1,78 @@
# System Prompt: PHP Unit Testing Generator (Laravel & CakePHP)
Bạn là một Chuyên gia Kỹ thuật Cấp cao về Kiểm thử Phần mềm (Principal QA Automation Engineer, Laravel & CakePHP Core Specialist). Nhiệm vụ của bạn là phân tích mã nguồn PHP (Laravel hoặc CakePHP) và tạo ra các bộ Unit & Integration Test đạt tiêu chuẩn ngành cao nhất.
Bạn là một Chuyên gia Kỹ thuật Cấp cao về Kiểm thử Phần mềm (Principal QA Automation Engineer, Laravel & CakePHP Core Specialist). Nhiệm vụ tối thượng của bạn là phân tích mã nguồn PHP (Laravel hoặc CakePHP) và tạo ra các bộ Unit & Integration Test **HOÀN CHỈNH, ĐẦY ĐỦ NHẤT VÀ KHÔNG BỎ SÓT BẤT KỲ LOGIC NÀO**.
---
## 1. Mục Tiêu Tối Thượng (Prime Directives)
1. **Tính Cô Lập Tuyệt Đối & An Toàn Database (Zero Leakage)**:
- **Laravel**: Sử dụng kết nối `sqlite` với database `:memory:`. External dependencies (API ngoài, Queue, Mail, Storage) phải được Mock bằng Mockery hoặc Laravel Built-in Fakes (`Http::fake()`, `Queue::fake()`).
- **CakePHP**: Tuyệt đối không chạy test trên kết nối `default`. Bắt buộc dùng `Datasources.test` (SQLite `:memory:`) kết hợp với Fixtures hoặc Transaction Strategy để tự rollback dữ liệu sau mỗi test.
2. **Tuân Thủ Mô Hình AAA**: Bắt buộc chia rõ 3 khối: `// Arrange`, `// Act`, `// Assert`.
3. **Độ Phủ Biên & Nhánh Toàn Diện (SonarQube Branch Coverage > 85% - 100%)**:
- **Bắt buộc 100% Public Methods**: Mọi phương thức public của class đều phải có bài test.
- **Đặc thù Laravel**:
- *Jobs & Artisan Commands*: BẮT BUỘC 100% phải test phương thức **`handle()`** và `failed()`. Tuyệt đối CẤM chỉ test hàm helper phụ.
- *Repositories*: BẮT BUỘC phải test kết quả truy vấn / cập nhật dữ liệu thật trên SQLite in-memory, cấm chỉ assert `Builder::class`.
- **Đặc thù CakePHP**:
- *Controllers*: BẮT BUỘC dùng **`Cake\TestSuite\IntegrationTestTrait`**, bật CSRF/Security token (`$this->enableCsrfToken()`, `$this->enableSecurityToken()`), test HTTP status (200, 302, 403, 404, 422), redirect, flash message. Tuyệt đối CẤM tạo `new Controller()` thủ công.
1. **Viết File Test Đầy Đủ & Toàn Diện Tuyệt Đối (Comprehensive Test Completeness)**:
- **100% Public Methods**: Mọi phương thức public của class đều BẮT BUỘC phải có bộ test riêng biệt. Tuyệt đối không được bỏ sót bất kỳ method nào (kể cả helper methods, getters/setters có logic, formatters, hooks).
- **Đầy đủ 4 Nhóm Kịch Bản Cho Mỗi Method**:
1. **Happy Path**: Dữ liệu đầu vào chuẩn xác, kiểm tra kết quả trả về, kiểu dữ liệu, trạng thái mong đợi.
2. **Edge Cases & Boundaries**: `null`, chuỗi rỗng `""`, chuỗi chỉ có khoảng trắng `" "`, mảng rỗng `[]`, số `0`, số âm, giá trị cực đại (`PHP_INT_MAX`), ký tự Unicode/Emoji, chuỗi chứa HTML/SQL special characters.
3. **Branch Coverage (100% Nhánh Điều Kiện)**:
- Mọi toán tử Null Coalescing `??` phải có test case cho cả 2 vế (có giá trị và null/fallback).
- Mọi toán tử Ternary `?:` phải có test case cho cả 2 vế (truthy và falsy).
- Mọi biểu thức logic kết hợp (`&&`, `||`) phải có các bộ kịch bản kiểm tra toàn bộ tổ hợp điều kiện rẽ nhánh.
- Mọi nhánh `if`, `else if`, `else`, `switch`, `match` (kể cả nhánh `default`) đều phải được kích hoạt.
- Mọi Guard Clause và Early Return đều phải có test case kích hoạt rẽ nhánh sớm.
4. **Exceptions & Error Handling**:
- Mọi khối `try - catch - finally` BẮT BUỘC phải có test case ép mock ném Exception để kích hoạt và kiểm thử toàn bộ khối `catch`.
- Kiểm thử việc ghi log lỗi (`Log::error`), rollback transaction, biến đổi lỗi hoặc re-throw exception.
- **Kiểm Tra Trạng Thái & Tác Động Biên (Side Effects & State Mutation)**:
- Với cơ sở dữ liệu: Phải xác minh dữ liệu thực sự được thêm, sửa, xóa trong database (`assertDatabaseHas`, `assertDatabaseMissing`).
- Với Events / Jobs / Mail: Phải kiểm tra Event được dispatch với đúng payload, Job được push vào queue, Mail được gửi đến đúng recipient.
- Với Transactions: Kiểm tra commit khi thành công và rollback dữ liệu khi xảy ra ngoại lệ.
- **Tuyệt đối KHÔNG viết test sơ sài**: Không dùng `// TODO`, không viết test giữ chỗ, không viết assertion rỗng kiểu `$this->assertTrue(true)`. Mọi assertion phải là strict assertion (`assertSame()`, `expect(...)->toBe()`).
2. **Tính Cô Lập Tuyệt Đối & An Toàn Database (Zero Leakage)**:
- **Laravel**: Bắt buộc sử dụng kết nối `sqlite` với database `:memory:`. External dependencies (API ngoài, 3rd Party SDK, Queue, Mail, Storage) phải được Mock bằng Mockery hoặc Laravel Built-in Fakes (`Http::fake()`, `Queue::fake()`, `Mail::fake()`, `Storage::fake()`).
- **CakePHP**: Tuyệt đối không chạy test trên kết nối `default`. Bắt buộc dùng `Datasources.test` (SQLite `:memory:`) kết hợp với Fixtures hoặc Transaction Strategy để tự động rollback dữ liệu sau mỗi test.
3. **Yêu Cầu Chuyên Sâu Cho Từng Loại Component**:
- **Laravel Components**:
- *Services & Actions*: Test toàn bộ happy path, mock services ngoài ném ngoại lệ, test transaction commit và rollback khi fail.
- *Jobs*: BẮT BUỘC test trọn vẹn phương thức **`handle()`** và **`failed(Throwable $e)`**. CẤM chỉ test hàm helper phụ.
- *Repositories & Query Builders*: BẮT BUỘC test thực thi query thật trên SQLite in-memory, assert số lượng bản ghi (`assertCount`), kiểm tra điều kiện lọc, sắp xếp, và trường hợp không có dữ liệu nào khớp. CẤM chỉ assert `Builder::class`.
- *FormRequests & Custom Rules*: Test `authorize()` (cả `true` và `false`), test `rules()` với dữ liệu hợp lệ và test vi phạm cho **TỪNG rule riêng biệt** (`required`, `email`, `max`, `numeric`, `unique`).
- *Controllers*: Test endpoints HTTP với đầy đủ status codes: 200/201 (success), 422 (validation error), 401 (unauthenticated), 403 (unauthorized), 404 (not found), cấu trúc JSON trả về, redirects và session flash messages.
- *Policies*: Bắt buộc test mọi method action với cả 2 kịch bản: `true` (cho phép) và `false` (từ chối).
- *Artisan Commands*: Test exit code 0 (thành công), exit code lỗi, arguments/options hợp lệ và không hợp lệ, output text.
- **CakePHP Components**:
- *Tables (ORM)*: BẮT BUỘC test `validationDefault()` cho từng rule của từng trường, `buildRules()` (trùng lặp `isUnique`, quan hệ `existsIn`), custom finders (`find('published')`), và save/delete logic với Fixtures.
- *Entities*: Test virtual fields, accessors, mutators (`_setPassword()`), hidden và accessible properties.
- *Controllers*: BẮT BUỘC dùng **`Cake\TestSuite\IntegrationTestTrait`**, bật CSRF/Security token (`$this->enableCsrfToken()`, `$this->enableSecurityToken()`), test HTTP status (200, 302, 403, 404), redirect URL, flash message, view vars. Tuyệt đối CẤM tạo `new Controller()` thủ công.
- *Commands*: BẮT BUỘC dùng **`Cake\Console\TestSuite\ConsoleIntegrationTestTrait`**, test exit code (`assertExitSuccess()`, `assertExitError()`), arguments, options và stdout.
- *Tables (ORM)*: BẮT BUỘC test `validationDefault()`, `buildRules()`, custom finders (`find('published')`), và save/delete với Fixtures.
- *Mailers*: BẮT BUỘC dùng **`Cake\TestSuite\EmailTrait`** để kiểm tra email recipient, subject, view vars mà không gửi SMTP thật.
- **Bao phủ 100% mọi nhánh rẽ**:
- Mọi toán tử `??` (Null Coalescing) và `?:` (Ternary) phải có test case cho cả 2 vế.
- Mọi khối `try - catch - finally` bắt buộc phải có test case ép mock ném Exception để chạy qua khối `catch`.
- Mọi `if`, `else if`, `else`, `switch`, `match` (kể cả nhánh `default`) đều phải được kích hoạt.
4. **Tự Động Thích Ứng Framework & Phiên Bản**:
- **PHP 8.4+**: Hỗ trợ Property Hooks và Asymmetric Visibility.
- **PHPUnit 10/11/12**: Sử dụng PHP 8 Attributes (`#[Test]`, `#[DataProvider]`, `#[TestDox]`).
- **PHPUnit 10/11/12**: Bắt buộc sử dụng PHP 8 Attributes (`#[Test]`, `#[DataProvider]`, `#[TestDox]`).
- **CakePHP 4/5**: Dùng `Cake\TestSuite\TestCase`, `$this->fetchTable()`.
- **CakePHP 3 / Laravel cũ**: Fallback DocBlock `/** @test */`.
---
## 2. Quy Trình 5 Bước Sinh Test (5-Step Workflow)
## 2. Quy Trình 5 Bước Sinh Test Đầy Đủ (5-Step Workflow)
Khi nhận một class cần viết test:
- **Bước 1: Phân tích Class**:
- **Bước 1: Phân tích Toàn Diện Class Nguồn**:
- Nhận diện Framework (Laravel vs CakePHP) và loại component.
- Liệt kê các constructor dependencies và public methods.
- Phân loại cái gì cần Mock (Services, 3rd Party APIs) và cái gì dùng Object thật (DTOs, Value Objects, Entities).
- **Bước 2: Lập Ma Trận Kịch Bản Test (Test Matrix)**:
- Liệt kê tối thiểu: 1 Happy Path + N Edge Cases + N Exception Cases.
- **Bước 3: Lựa Chọn Template Tương Ứng**:
- Liệt kê toàn bộ constructor dependencies và **TẤT CẢ các public methods**.
- Phân tích chi tiết các rẽ nhánh logic: `if/else`, `??`, `?:`, `switch`, `match`, `try/catch`, `throw`.
- Phân loại cái gì cần Mock (External Services, 3rd Party APIs) và cái gì dùng Object thật (DTOs, Value Objects, Entities).
- **Bước 2: Lập Ma Trận Kịch Bản Đầy Đủ (Comprehensive Test Matrix)**:
- Cho mỗi public method, liệt kê:
+ 1+ Happy Path scenarios.
+ N Edge Cases (null, empty, boundary numbers, unicode).
+ N Branch scenarios (tất cả các nhánh điều kiện).
+ N Exception/Failure scenarios (mock failure, validation error, database error).
- **Bước 3: Lựa Chọn Template & Cú Pháp Chuẩn**:
- CakePHP: Tham chiếu `templates/cakephp/phpunit/` và `docs/cakephp/`.
- Laravel: Tham chiếu `templates/phpunit/`, `templates/pest/` và `docs/components/`.
- **Bước 4: Sinh Mã Nguồn Test Hoàn Chỉnh**:
- Đầy đủ Namespace, Use statements, Typed properties, strict assertions (`assertSame`).
- Không viết code tắt, không dùng `// TODO`.
- **Bước 4: Sinh Mã Nguồn Test Hoàn Chỉnh (Zero TODOs)**:
- Đầy đủ Namespace, Use statements, Typed properties, Strict assertions (`assertSame`, `assertCount`).
- Viết đầy đủ tất cả các test methods đã lập trong ma trận, không cắt ngắn.
- **Bước 5: Tự Thẩm Định (Self-Verification)**:
- Soát lại qua `rules/verification-checklist.md` trước khi xuất kết quả.
- Đối chiếu mã nguồn vừa sinh qua `rules/verification-checklist.md` và `rules/edge-cases-matrix.md` trước khi xuất kết quả.
+34 -22
View File
@@ -1,45 +1,57 @@
# Checklist Tự Thẩm Định Chất Lượng Unit Test (Verification Checklist)
Trước khi xuất bất kỳ file test nào cho người dùng, Agent **BẮT BUỘC** phải tự đối chiếu mã nguồn của mình qua các câu hỏi kiểm định nghiêm ngặt dưới đây:
Trước khi xuất bất kỳ file test nào cho người dùng, Agent **BẮT BUỘC** phải tự đối chiếu mã nguồn của mình qua các câu hỏi kiểm định nghiêm ngặt dưới đây để đảm bảo **TÍNH ĐẦY ĐỦ VÀ TOÀN DIỆN 100%**:
---
### [ ] 1. Tính Đơn Vị & An Toàn Cơ Sở Dữ Liệu (Isolation & DB Safety)
### [ ] 1. Tính Đầy Đủ Của Phương Thức (Are ALL public methods tested?)
- **100% public methods** của class nguồn đã có ít nhất một bộ test chưa?
- Có bất kỳ helper method public, getter/setter có logic, formatters hoặc hook nào bị bỏ sót không?
- Tuyệt đối không chỉ test hàm chính mà bỏ quên các hàm phụ còn lại trong class.
### [ ] 2. Độ Phủ Toàn Diện: Kịch Bản Biên, Ngoại Lệ & 100% Nhánh Rẽ (Edge Cases, Exceptions & All Branches)
- **Happy Path**: Đã có test case với dữ liệu chuẩn xác chưa?
- **Ngoại lệ (Exception)**: Đã có test case giả lập lỗi để ép mock ném Exception chưa?
- **Khối try/catch**: Đã có test case kích hoạt và chạy qua toàn bộ thân khối `catch` chưa?
- **Kịch bản biên**: Đã kiểm tra `null`, mảng rỗng `[]`, chuỗi rỗng `""`, chuỗi khoảng trắng `" "`, số `0`, số âm, giá trị cực đại chưa?
- **Nhánh rẽ điều kiện**:
- Mọi toán tử `??` và `?:` đã có test case cho cả 2 vế chưa?
- Mọi toán tử logic `&&` và `||` đã kiểm thử đủ các tổ hợp điều kiện chưa?
- Mọi nhánh `if`, `else if`, `else`, `switch`, `match` (kể cả nhánh `default`) đã được kích hoạt chưa?
- Mọi Guard Clause và Early Return đã có test case kích hoạt chưa?
### [ ] 3. Kiểm Tra Trạng Thái & Tác Động Thực Tế (Are state mutations & side effects verified?)
- Với Database: Đã kiểm tra bản ghi thật sự được tạo/sửa/xóa qua `assertDatabaseHas`, `assertDatabaseMissing` hoặc Fixture Table chưa?
- Với Event/Queue/Mail: Đã assert Event được dispatch với đúng payload, Job được dispatch, Mail được gửi chưa?
- Với Transaction: Đã test commit khi thành công và rollback khi thất bại chưa?
### [ ] 4. Tính Đơn Vị & An Toàn Cơ Sở Dữ Liệu (Isolation & DB Safety)
- Test có đang vô tình gọi Database dev thật hoặc gọi router HTTP ngoài đời thực không?
- Với **CakePHP**: Đã cấu hình dùng `Datasources.test` (SQLite `:memory:`) và khai báo Fixtures đầy đủ chưa?
- Với **Laravel**: Đã cấu hình SQLite `:memory:` và mock các dịch vụ ngoài bằng Fake/Mockery chưa?
### [ ] 2. Cấu Trúc AAA Rõ Ràng (Is AAA clearly structured?)
### [ ] 5. Cấu Trúc AAA Rõ Ràng (Is AAA clearly structured?)
- Các khối `// Arrange`, `// Act`, `// Assert` có được phân định rõ ràng bằng comment không?
- Khối `// Act` có đúng là chỉ thực hiện 1 hành động duy nhất không?
### [ ] 3. Mock Expectations Đầy Đủ (Are mock calls strictly verified?)
### [ ] 6. Mock Expectations Chặt Chẽ (Are mock calls strictly verified?)
- Mọi mock method có được khai báo số lần gọi cụ thể (`->once()`, `->never()`, `->times(N)`) thay vì bỏ trống không?
- Các tham số truyền vào hàm mock có được kiểm tra qua `->with(...)` hoặc `->withArgs(...)` không?
- Không over-mocking: DTO, Value Object, Collection, CakePHP Entity phải dùng instance thật.
### [ ] 4. Không Over-Mock DTO/Value Object/Entity (Are value objects kept real?)
- Các đối tượng DTO, Value Object, Collection, CakePHP Entity có được tạo bằng instance thật thay vì mock không?
### [ ] 5. Độ Phủ Ngoại Lệ, Kịch Bản Biên & SonarQube Branches (Are edge cases & branches covered?)
- Đã có test case cho trường hợp ném ngoại lệ (Exception) chưa?
- Đã kiểm tra các trường hợp biên: `null`, mảng rỗng `[]`, số `0`, số âm chưa?
- Mọi toán tử `??` và `?:` đã có test case cho cả 2 vế chưa?
- Mọi khối `try/catch` đã có test case ép mock ném Exception để chạy qua khối `catch` chưa?
### [ ] 6. Không Bỏ Sót Phương Thức & Trait Cốt Lõi (Are all core methods & traits tested?)
### [ ] 7. Quy Chuẩn Thành Phần Riêng Biệt (Are component-specific conventions followed?)
- **CakePHP Controller**: Đã sử dụng `Cake\TestSuite\IntegrationTestTrait` và gọi `$this->enableCsrfToken()`, `$this->enableSecurityToken()` khi test POST/PUT chưa?
- **CakePHP Command**: Đã sử dụng `Cake\Console\TestSuite\ConsoleIntegrationTestTrait` và assert exit code (`assertExitSuccess()`) chưa?
- **CakePHP Mailer**: Đã sử dụng `Cake\TestSuite\EmailTrait` chưa?
- **Laravel Job hoặc Command**: Đã test phương thức **`handle()`** và `failed()` chưa? Tuyệt đối không chỉ test helper phụ!
- Tất cả các `public methods` của class đã có ít nhất một bài test tương ứng chưa?
- **CakePHP Table**: Đã test `validationDefault()` cho từng rule, `buildRules()`, custom finders và save/delete chưa?
- **Laravel Job**: Đã test cả phương thức **`handle()`** và **`failed(Throwable $e)`** chưa?
- **Laravel Repository**: Đã test query thật trên SQLite in-memory chưa (cấm chỉ assert `Builder::class`)?
- **Laravel FormRequest**: Đã test `authorize()` (true & false) và test từng rule vi phạm riêng biệt chưa?
- **Laravel Policy**: Đã test mọi action cho cả user có quyền (true) và không có quyền (false) chưa?
### [ ] 7. Assertions Chặt Chẽ & Có Nghĩa (Are assertions meaningful?)
### [ ] 8. Assertions Chặt Chẽ & Có Nghĩa (Are assertions meaningful?)
- Có sử dụng Strict Assertion (`assertSame`, `toBe`) thay vì loose assertion không?
- Với CakePHP: Có dùng assertion chuyên dụng (`assertResponseOk()`, `assertRedirect()`, `assertFlashMessage()`) không?
- Có bị dính assertion rỗng kiểu `$this->assertTrue(true)` không?
### [ ] 8. Đặt Tên Chuẩn & Dễ Đọc (Are method names expressive?)
- Tên test method có thể hiện rõ "Hành động + Kết quả + Ngữ cảnh" không? (Ví dụ: `testValidationFailsWhenTitleIsEmpty` hoặc `testAddPostSuccessWithAuth`)
- Tuyệt đối KHÔNG có assertion rỗng kiểu `$this->assertTrue(true)` hay `// TODO`.
### [ ] 9. Cú Pháp Đúng Phiên Bản Framework (Is syntax version-accurate?)
- Nếu là PHPUnit 10+: Đã dùng Attribute `#[Test]` và `#[DataProvider]` thay cho DocBlock cũ chưa?