sinau-c/test-load/README.md

455 lines
11 KiB
Markdown

# Load Test untuk Elemes LMS
Load test ini menggunakan **Locust** untuk mensimulasikan traffic pengguna pada LMS Elemes (Sinau-C).
## ⚠️ Penting: Keamanan Data Siswa
Load test ini menggunakan **token siswa test** yang ditunjuk khusus untuk testing:
**Student Test Tokens (rows 40-72 di `tokens_siswa.csv`):**
- CC90965E (ACHMAD RAFFY IRSYAD RAMADHAN)
- F84E3336 (AHMAD GHAUZAN AZRIL IRAWAN)
- D78F6DBD (AINI BINTANG PRAMESWARI)
- ... dan 30 siswa lainnya sampai SATRIYO WICAKSONO
**Teacher Token:**
- 141214 (Anggoro Dwi - untuk view-only operations)
Token-token ini aman untuk testing karena:
1. ✅ Bukan siswa aktif yang sedang belajar
2. ✅ Progress mereka bisa di-reset dengan mudah
3. ✅ Teacher token hanya untuk read-only operations
4. ✅ Semua write operations (track-progress) menggunakan test student tokens
## Struktur File
```
test-load/
├── locustfile.py # Script load test utama
├── requirements.txt # Dependencies Python
└── README.md # Dokumentasi ini
```
## Instalasi
### 1. Buat Virtual Environment (Opsional tapi Direkomendasikan)
```bash
cd test-load
python3 -m venv venv
source venv/bin/activate # Linux/Mac
# atau
venv\Scripts\activate # Windows
```
### 2. Install Dependencies
```bash
pip install -r requirements.txt
```
## Cara Menjalankan
### 🚀 Quick Start (Menggunakan Script Helper)
Cara termudah untuk menjalankan load test adalah menggunakan script `run.sh` yang sudah menyertakan setup venv otomatis:
```bash
cd test-load
# Test API (Flask backend :5000)
./run.sh
# Test Frontend (SvelteKit :3000) - HTML pages
./run.sh frontend
# Test Full Stack (Frontend + API via proxy)
./run.sh fullstack
# Jalankan headless mode (default: 50 users, 5 spawn rate, 60 detik)
./run.sh headless
# Custom parameters
./run.sh headless -u 100 -r 10 -t 5m
./run.sh headless frontend -u 200 -r 20 -t 300s
# Hapus virtual environment
./run.sh clean
```
### Mode Web UI (Interaktif)
```bash
# Menggunakan script helper (recommended)
# Test API only (Flask backend :5000)
./run.sh
# Test Frontend only (SvelteKit :3000) - loads HTML pages
./run.sh frontend
# Test Full Stack (Frontend proxies /api to Flask)
./run.sh fullstack
# Atau manual dengan venv
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# API testing
locust -f locustfile.py --host=http://localhost:5000
# Frontend testing
locust -f locustfile.py --host=http://localhost:3000
```
Kemudian buka browser di: **http://localhost:8089**
Di Web UI, Anda bisa:
- Set jumlah user (Total Users)
- Set spawn rate (user per detik)
- Start, Stop, dan Edit load test secara real-time
- Melihat grafik response time, requests/detik, failures
### Mode Headless (CLI/Scripted)
```bash
# Menggunakan script helper
# Test API
./run.sh headless -u 100 -r 10 -t 300s
# Test Frontend (HTML pages)
./run.sh headless frontend -u 100 -r 10 -t 5m
# Test Full Stack
./run.sh headless fullstack -u 200 -r 20 -t 10m
# Atau manual
source venv/bin/activate
# API testing (Flask :5000)
locust -f locustfile.py --host=http://localhost:5000 --headless -u 100 -r 10 -t 300s
# Frontend testing (SvelteKit :3000)
locust -f locustfile.py --host=http://localhost:3000 --headless -u 100 -r 10 -t 300s
```
### Mode Distributed (Multi-Machine)
Untuk load test skala besar:
```bash
# Master node
locust -f locustfile.py --headless -u 1000 -r 100 --master
# Worker node 1
locust -f locustfile.py --worker --master-host=192.168.1.100
# Worker node 2
locust -f locustfile.py --worker --master-host=192.168.1.100
```
## Parameter CLI
| Parameter | Deskripsi | Contoh |
|-----------|-----------|--------|
| `-u` | Total jumlah user simulasi | `-u 100` |
| `-r` | Spawn rate (user per detik) | `-r 10` |
| `-t` | Durasi test | `-t 300s`, `-t 5m`, `-t 1h` |
| `--host` | Target URL | `--host=http://localhost:5000` |
| `--headless` | Jalankan tanpa UI | `--headless` |
| `--html` | Export hasil ke HTML | `--html=report.html` |
## User Classes
Load test ini memiliki 4 kelas user:
### 1. FrontendUser (Weight: 5)
Mensimulasikan user yang browsing halaman web frontend:
- Load homepage (/)
- Load lesson pages (/lesson/[slug])
- Load progress page (/progress)
- Load static assets (CSS, JS, manifest)
**Weight 5** = Testing beban pada SvelteKit frontend
### 2. StudentUser (Weight: 8)
Mensimulasikan siswa yang berinteraksi dengan API:
- Login dengan token
- Melihat daftar pelajaran (API)
- Membuka konten lesson (API)
- Compile kode C
- Validate token
- Logout
**Weight 8** = 40% traffic adalah siswa (API)
### 3. TeacherUser (Weight: 2)
Mensimulasikan guru yang berinteraksi dengan API:
- Login dengan token guru
- Melihat progress report (API)
- Export CSV progress
- Membuka lesson untuk review
- Validate token
**Weight 2** = 10% traffic adalah guru (API)
### 4. APIStressTest (Weight: 1)
Stress test endpoint API spesifik:
- `/api/compile` - Code compilation
- `/api/lesson/[slug].json` - Lesson content
- `/api/validate-token` - Token validation
- `/api/lessons` - Lessons list
**Weight 1** = 5% traffic adalah stress test API
## Endpoint yang Diuji
### Frontend (SvelteKit :3000)
| Endpoint | Method | Fungsi | User Class |
|----------|--------|--------|------------|
| `/` | GET | Homepage (lesson grid) | FrontendUser |
| `/lesson/[slug]` | GET | Lesson page | FrontendUser |
| `/progress` | GET | Progress report page | FrontendUser |
| `/_app/immutable/*` | GET | Static JS/CSS assets | FrontendUser |
| `/manifest.json` | GET | PWA manifest | FrontendUser |
| `/circuitjs1/circuitjs.html` | GET | Circuit simulator | FrontendUser |
### Backend API (Flask :5000)
| Endpoint | Method | Fungsi | User Class |
|----------|--------|--------|------------|
| `/api/login` | POST | Login dengan token | Student, Teacher |
| `/api/logout` | POST | Logout | Student |
| `/api/validate-token` | POST | Validasi token | Student, Teacher, Stress |
| `/api/lessons` | GET | Daftar pelajaran | Student, Teacher, Stress |
| `/api/lesson/<slug>.json` | GET | Konten lesson | Student, Teacher, Stress |
| `/api/compile` | POST | Compile & run kode | Student, Stress |
| `/api/progress-report.json` | GET | Progress report | Teacher |
| `/api/progress-report/export-csv` | GET | Export CSV | Teacher |
## Contoh Skenario Testing
### 1. Load Test Ringan (Development)
```bash
# API only
./run.sh headless -u 20 -r 2 -t 60s
# Frontend
./run.sh headless frontend -u 20 -r 2 -t 60s
```
### 2. Load Test Sedang (Staging)
```bash
# API only
./run.sh headless -u 100 -r 10 -t 300s
# Full Stack (Frontend + API)
./run.sh headless fullstack -u 100 -r 10 -t 300s
```
### 3. Load Test Berat (Production Capacity Test)
```bash
# API only
./run.sh headless -u 500 -r 50 -t 600s
# Frontend
./run.sh headless frontend -u 500 -r 50 -t 600s
```
### 4. Stress Test (Find Breaking Point)
```bash
./run.sh headless fullstack -u 1000 -r 100 -t 300s
```
### 5. Endurance Test (Stability Test)
```bash
./run.sh headless fullstack -u 50 -r 5 -t 2h
```
### 6. Frontend Page Load Test
```bash
# Test HTML page rendering + static assets
./run.sh headless frontend -u 100 -r 10 -t 5m
```
## Metrik yang Dipantau
### Di Web UI
- **RPS**: Requests per second
- **Average Response Time**: Rata-rata waktu response
- **Median Response Time**: Response time median
- **95th Percentile**: 95% request lebih cepat dari nilai ini
- **Failures**: Jumlah request gagal
### Log Console
- Slow requests (>1 detik)
- Total requests
- Failure rate (%)
- Average response time
## Threshold Performance
Berikut threshold yang direkomendasikan untuk LMS:
| Metrik | Target | Warning | Critical |
|--------|--------|---------|----------|
| Avg Response Time | <200ms | 200-500ms | >500ms |
| 95th Percentile | <500ms | 500-1000ms | >1000ms |
| Failure Rate | <0.1% | 0.1-1% | >1% |
| RPS Capacity | >100 | 50-100 | <50 |
## Export Hasil
### HTML Report
```bash
locust -f locustfile.py --host=http://localhost:5000 --headless -u 100 -r 10 -t 300s --html=report.html
```
### CSV Statistics
```bash
locust -f locustfile.py --host=http://localhost:5000 --headless -u 100 -r 10 -t 300s --csv=results
```
Output:
- `results_requests.csv`
- `results_failures.csv`
- `results_stats.csv`
- `results_history.csv`
### JSON (via events)
Tambahkan ke `locustfile.py`:
```python
@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
import json
stats = {
'total_requests': environment.stats.total.num_requests,
'failures': environment.stats.total.num_failures,
'avg_response_time': environment.stats.total.avg_response_time,
}
with open('results.json', 'w') as f:
json.dump(stats, f)
```
## Troubleshooting
### User Count Tidak Sesuai (Misal: Set 50, Yang Muncul 19)
**Penyebab:**
1. **User class gagal start** - Task error atau on_start error
2. **Host tidak reachable** - Server target belum running
3. **Weight distribution** - Locust mendistribusikan user berdasarkan weight
**Solusi:**
1. **Periksa log console** untuk error messages:
```bash
./run.sh 2>&1 | grep -i error
```
2. **Pastikan server target running**:
```bash
# Untuk API testing (:5000)
curl http://localhost:5000/api/lessons
# Untuk Frontend testing (:3000)
curl http://localhost:3000/
```
3. **Gunakan mode yang sesuai**:
```bash
# API only - jangan gunakan frontend user
./run.sh headless -u 50 -r 5
# Frontend only
./run.sh headless frontend -u 50 -r 5
# Full stack (recommended)
./run.sh headless fullstack -u 50 -r 5
```
4. **Cek user count di log**:
```
✅ Spawning complete: 50 users active
```
5. **Disable user class yang tidak perlu** dengan edit weight di `locustfile.py`:
```python
class FrontendUser(HttpUser):
weight = 0 # Disable
```
### Error: "Connection refused"
Pastikan backend/frontend berjalan:
```bash
# API (Flask)
cd elemes
python app.py
# Frontend (SvelteKit)
cd elemes/frontend
npm run dev
```
### Response time sangat tinggi
Kemungkinan penyebab:
- Backend overload (kurangi user count)
- Network latency (jalankan load test di network yang sama)
- Database/file I/O bottleneck (periksa logs Flask)
### High failure rate
Periksa:
- Token guru valid di `tokens_siswa.csv`
- Content folder ada dan berisi file .md
- Flask logs untuk error detail
### FrontendUser tidak muncul di panel
Jika testing di `:5000` (API), FrontendUser otomatis disabled karena halaman web tidak ada di Flask backend. Gunakan `:3000` untuk frontend testing.
## Tips
1. **Mulai kecil**: Mulai dengan 10-20 user, naikkan bertahap
2. **Monitor resources**: Gunakan `htop`, `docker stats` saat testing
3. **Test di staging**: Jangan test load tinggi langsung di production
4. **Baseline first**: Jalankan test sekali untuk dapat baseline metrics
5. **Compare runs**: Simpan hasil untuk perbandingan setelah perubahan code
## Integrasi CI/CD
### GitHub Actions Example
```yaml
name: Load Test
on: [push]
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
cd test-load
pip install -r requirements.txt
- name: Run load test
run: |
cd test-load
locust -f locustfile.py --host=http://localhost:5000 \
--headless -u 50 -r 5 -t 60s --fail-on-ratio=0.01
```
## Referensi
- [Locust Documentation](https://docs.locust.io/)
- [Elemes Documentation](../elemes/documentation.md)
- [Elemes README](../elemes/README.md)