# 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/.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)