parfum/tests/GUIDELINES.md

141 lines
4.5 KiB
Markdown

# Testing Guideline (Pest + Laravel + Livewire 3)
Dokumen ini adalah **aturan wajib** dan **acuan tunggal** untuk seluruh penulisan testing.
Tujuannya:
- Konsistensi Mutlak (Uniformity)
- Realistis sesuai flow aplikasi (No shortcuts)
- Mudah dipahami AI dan manusia
- Tidak ada logic testing yang "ngawang" atau "magic"
---
## 1. Tech Stack & Referensi Resmi
Wajib mengacu pada dokumen berikut:
- Pest PHP → https://pestphp.com
- Livewire 3 Testing → https://livewire.laravel.com/docs/3.x/testing
- Laravel Testing → https://laravel.com/docs/testing
Framework lain, pendekatan custom, atau eksperimen **DILARANG KERAS**.
---
## 2. Aturan Global Testing (STRICT MODE)
### 2.1 Struktur Wajib (Seragam)
- **SELALU gunakan `beforeEach()`** untuk setup awal.
- Tidak boleh membuat data user secara inline di dalam test.
- Semua logic setup yang berulang **harus di-extract ke helper method** di `Pest.php`.
### 2.2 Strict Data Generation (Factory ONLY)
- **WAJIB menggunakan Factory** untuk semua pembuatan data database.
- **DILARANG** menggunakan `new Model()` atau `Model::create()` secara manual di dalam file test.
- Jika butuh data spesifik, gunakan `.state()` atau `factory(['key' => 'value'])`.
- **Predictable Data**: Gunakan hardcoded string atau value yang pasti (misal: `test@example.com`, `Secret123!`) di dalam test assertion daripada mengandalkan random data dari factory yang tidak terukur.
Contoh dasar setup:
```php
beforeEach(function () {
$this->setupUser();
});
```
Helper `setupUser` di `Pest.php` (CONTOH STANDAR):
```php
function setupUser(array $overrides = []): void
{
$test = test();
$test->user = User::factory()->create($overrides);
$test->employee = Employee::factory()->for($test->user)->create();
$test->outlet = Outlet::factory()->create();
$test->user->outlets()->attach($test->outlet);
$test->openingHours = OpeningHour::factory()->count(3)->create();
$test->outlet->openingHours()->attach($test->openingHours->pluck('id')->toArray());
}
```
---
## 3. Business Rules (NON-NEGOTIABLE)
### 3.1 Relasi User & Role
Flow HARUS REALISTIS, tidak boleh ada shortcut logic:
- **User -> Employee**: One-to-one (Wajib ada).
- **User -> Outlets**: Many-to-many (Wajib minimal 1 outlet).
- **Outlet -> Opening Hours**: Wajib ada data jam operasional.
- **Role/Permissions**: Harus di-assign secara eksplisit di setup jika test tersebut mengecek otorisasi.
Jika ada test yang melompati relasi ini (misal: User tanpa Outlet tapi bisa transaksi) → **TEST TIDAK VALID**.
---
## 4. Struktur Folder & File
### 4.1 Pemisahan Component (WAJIB)
Setiap Livewire Component harus memiliki file test sendiri:
```
tests/Feature/
├── Auth/
│ ├── LoginTest.php
│ └── ForgotPasswordTest.php
├── User/
│ ├── IndexTest.php
│ ├── CreateTest.php
│ └── EditTest.php
```
**DILARANG** menggabungkan Create/Update/Delete dalam satu file jika component-nya berbeda.
---
## 5. Scope Testing (STRICT CHECKLIST)
### 5.1 Otorisasi (The "Can/Cannot" Principle)
Wajib test setiap level akses:
- Role A bisa akses?
- Role B tidak bisa akses?
- Gunakan `actingAs($this->user)`.
### 5.2 Validasi (Granular Testing)
- Test **setiap baris** aturan validasi yang ada di Form Object atau Component.
- Wajib test: `required`, `email`, `unique`, `min/max`.
- Gunakan predictable invalid data (misal: email tanpa '@').
### 5.3 UI & State Verification
- `assertSee()`: Pastikan text penting muncul.
- `assertSet()`: Pastikan property Livewire berubah.
- `assertDispatched()`: Pastikan event (toast/modal) terpanggil.
- **Database Verification**: Gunakan `assertDatabaseHas()` untuk memastikan data benar-benar tersimpan/berubah.
---
## 6. Penamaan Test (FORMAT BAKU)
Gunakan kalimat yang mendeskripsikan perilaku (behavioral):
- `it('renders the login page correctly')`
- `it('shows validation error when email is empty')`
- `it('redirects to dashboard after successful login')`
- `it('cannot delete user if not super-admin')`
---
## 7. Prinsip "Zero Assumption"
1. **Satu test = Satu Skenario**: Jangan menumpuk banyak assertion yang tidak relevan dalam satu `it()`.
2. **Hardcoded Assertions**: Jangan bandingkan data dengan data factory yang random. Bandingkan dengan value yang dimasukkan ke `->set()`.
3. **Clean Database**: Selalu gunakan `RefreshDatabase`.
---
## 8. Standarisasi AI & Developer
Jika Anda (AI atau Developer) menemukan kode yang tidak mengikuti standar ini:
- **TOLAK** implementasi tersebut.
- **REFACTOR** hingga sesuai guidelines.
- **JANGAN** pernah melakukan improvisasi yang mengurangi ketatnya aturan ini.