feat: enforce exhaustive unit testing and 100% SonarQube branch coverage

- Enforce mandatory handle() and failed() method testing for all Jobs and Commands
- Ban shallow reflection-only helper testing in Jobs
- Mandate actual SQLite in-memory query execution for Repositories (ban Builder::class assertions alone)
- Enforce full branch coverage for SonarQube (ternary, null-coalescing, catch blocks, match)
- Update JobTest templates for PHPUnit and Pest to include handle() and failed() methods
- Update verification checklist and master system prompt with strict branch gatekeepers

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 15:01:01 +07:00
parent c29bfb9c31
commit 0dce2ef812
7 changed files with 96 additions and 16 deletions
+14 -5
View File
@@ -83,10 +83,18 @@ Người dùng có thể kích hoạt linh hoạt theo các chế độ (từ qu
- **Dùng Laravel Fakes**: `Http::fake()`, `Queue::fake()`, `Event::fake()`, `Storage::fake()`.
- **Dùng Object thật (Không Mock)**: DTOs, Value Objects, Collections, Request payload dạng mảng.
### Bước 4: Lập Ma Trận Test Scenarios (Tối thiểu cho mỗi public method)
- **1 Happy Path**: Đầu vào hợp lệ -> Thực thi thành công -> Trả về đúng kết quả.
- **N Edge Cases**: Input biên (0, số âm, rỗng `""`, `[]`, `null`, unicode).
- **N Exception Cases**: Tham số sai ném `InvalidArgumentException`, service ngoài lỗi ném `PaymentFailedException`,...
### Bước 4: Lập Ma Trận Test Scenarios (Bắt Buộc Đầy Đủ & Không Bỏ Sót)
- **Bắt buộc 100% Public Methods**: Mọi phương thức public đều phải có test.
- *Nếu là Job / Command*: **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ụ (`buildRedisKey`) bằng reflection!
- *Nếu là Repository*: **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, tuyệt đối CẤM chỉ assert `Builder::class`!
- **Bao phủ 100% nhánh rẽ SonarQube**:
- 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.
- **Tối thiểu cho mỗi public method**:
- **1 Happy Path**: Đầu vào hợp lệ -> Thực thi thành công -> Trả về đúng kết quả.
- **N Edge Cases**: Input biên (0, số âm, rỗng `""`, `[]`, `null`, unicode).
- **N Exception Cases**: Tham số sai ném `InvalidArgumentException`, service ngoài lỗi ném `PaymentFailedException`,...
### Bước 5: Sinh Mã Nguồn Test
1. Xác định đường dẫn file test theo quy tắc Mirror:
@@ -95,8 +103,9 @@ Người dùng có thể kích hoạt linh hoạt theo các chế độ (từ qu
2. Tham chiếu hướng dẫn tương ứng trong `docs/components/` và template trong `templates/`.
3. Viết đầy đủ code:
- Tuân thủ mô hình **AAA** (`// Arrange`, `// Act`, `// Assert`).
- Mock expectation có số lần gọi rõ ràng: `->once()`, `->never()`.
- Mock expectation có số lần gọi nghiêm ngặt: `->once()`, `->never()`.
- Dùng Strict assertion: `$this->assertSame()` hoặc `expect(...)->toBe()`.
- Đảm bảo quét sạch tất cả các nhánh điều kiện để SonarQube Line & Branch Coverage đạt > 85% - 95%.
### Bước 6: Thẩm định & Lưu File
1. Tự kiểm tra file test qua `rules/verification-checklist.md`.