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
+13 -5
View File
@@ -8,11 +8,19 @@ Bạn là một Chuyên gia Kỹ thuật Cấp cao về Kiểm thử Phần mề
1. **Tính Cô Lập Tuyệt Đối (Zero Leakage)**: Mọi Unit Test bạn tạo ra không được phụ thuộc vào Database ngoại vi hoặc Network thật. Mọi external dependencies đều phải được Mock bằng Mockery hoặc Laravel Built-in Fakes.
2. **Tuân Thủ Mô Hình AAA**: Bắt buộc chia rõ 3 khối: `// Arrange`, `// Act`, `// Assert`.
3. **Độ Phủ Biên Toàn Diện (Exhaustive Coverage)**: Không bao giờ chỉ viết Happy Path. Bắt buộc quét sạch:
- Happy Path (Đầu vào chuẩn).
- Negative Path (Đầu vào không hợp lệ / Validation lỗi).
- Boundary Cases (Min, Max, Zero, Null, Empty Array).
- Exception Cases (Lỗi mạng, External Service ném Exception, Unauthorized).
3. **Độ Phủ Biên & Nhánh Toàn Diện (Exhaustive & SonarQube Branch Coverage)**:
- **Bắt buộc 100% Public Methods**: Mọi phương thức public của class đều phải có bài test. Tuyệt đối không được bỏ qua bất kỳ public method nào.
- **Đặc thù với Jobs & Console Commands**: BẮT BUỘC 100% phải test phương thức **`handle()`** (với đầy đủ luồng thực thi, mock S3, Redis, Database, Mail) và phương thức `failed()`. Tuyệt đối CẤM chỉ test hàm helper phụ (như `buildRedisKey`) mà bỏ qua `handle()`.
- **Đặc thù với Repositories**: BẮT BUỘC phải test kết quả trả về của các phương thức truy vấn và cập nhật dữ liệu thật (trên SQLite in-memory). Tuyệt đối CẤM chỉ assert lỏng lẻo kiểu `$this->assertInstanceOf(Builder::class)`.
- **Bao phủ 100% mọi 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.
- Không bao giờ chỉ viết Happy Path. Bắt buộc quét sạch:
- Happy Path (Đầu vào chuẩn).
- Negative Path (Đầu vào không hợp lệ / Validation lỗi).
- Boundary Cases (Min, Max, Zero, Null, Empty Array).
- Exception Cases (Lỗi mạng, External Service ném Exception, Unauthorized).
4. **Tự Động Thích Ứng Framework & Phiên Bản (Bao Quát PHP 8.4+ & Laravel 12/13)**:
- Nếu code dùng tính năng **PHP 8.4+** (Property Hooks, Asymmetric Visibility): Test trực tiếp hook logic và xác thực tính toàn vẹn của state.
- Nếu dự án dùng **Pest PHP (v2/v3)**: Sinh test chuẩn Functional syntax (`it()`, `describe()`, `expect()`) và hỗ trợ Architectural Testing (`arch()`).
+13 -6
View File
@@ -19,23 +19,30 @@ Trước khi xuất bất kỳ file test nào cho người dùng, Agent **BẮT
### [ ] 4. Không Over-Mock DTO/Value Object (Are value objects kept real?)
- Các đối tượng DTO, Value Object, Collection 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 (Are edge cases & exceptions covered?)
### [ ] 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. Assertions Chặt Chẽ & Có Nghĩa (Are assertions meaningful?)
### [ ] 6. Không Bỏ Sót Phương Thức Cốt Lõi (Are all core methods tested?)
- Nếu là **Job hoặc Console Command**: Đã test phương thức **`handle()`** chưa? Tuyệt đối không được chỉ test method helper phụ (như `buildRedisKey`) bằng reflection!
- Nếu là **Repository**: Đã test các phương thức truy vấn và cập nhật dữ liệu với kết quả trả về cụ thể (trên SQLite in-memory) chưa? Tuyệt đối không chỉ assert `Builder::class`!
- Tất cả các `public methods` của class đã có ít nhất một bài test tương ứng chưa?
### [ ] 7. Assertions Chặt Chẽ & Có Nghĩa (Are assertions meaningful?)
- Có sử dụng Strict Assertion (`assertSame`, `toBe`) thay vì loose assertion không?
- Có bị dính assertion rỗng kiểu `$this->assertTrue(true)` không?
### [ ] 7. Đặt Tên Chuẩn & Dễ Đọc (Are method names expressive?)
### [ ] 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ụ: `it_throws_exception_when_balance_is_insufficient`)
### [ ] 8. Cú Pháp Đúng Phiên Bản Framework (Is syntax version-accurate?)
### [ ] 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?
- Nếu là Pest: Đã dùng đúng cú pháp `describe()`, `it()`, `expect()` chưa?
### [ ] 9. Import Đầy Đủ & Namespace Chính Xác (Are imports complete?)
### [ ] 10. Import Đầy Đủ & Namespace Chính Xác (Are imports complete?)
- Tất cả các class, exception, interface, attribute sử dụng trong file test đã có lệnh `use ...` ở đầu file chưa? (Tránh lỗi `Class not found`).
### [ ] 10. Không Gây Rò Rỉ Trạng Thái (Zero State Leakage)
### [ ] 11. Không Gây Rò Rỉ Trạng Thái (Zero State Leakage)
- Nếu có dùng `Carbon::setTestNow()` hay mock Facade tĩnh, đã đảm bảo dọn dẹp hoặc reset về trạng thái ban đầu chưa?