455 lines
11 KiB
Markdown
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)
|