105 lines
3.3 KiB
Python
105 lines
3.3 KiB
Python
"""
|
|
Locust scenario khusus migrasi database (CSV → PostgreSQL).
|
|
|
|
Menargetkan endpoint yang persistence-nya berubah:
|
|
- /api/login + /api/validate-token (identitas: CSV → PG users/access_tokens)
|
|
- /api/track-progress (write progress: CSV → PG student_progress)
|
|
- /api/progress-report.json (report guru — baca semua siswa)
|
|
|
|
Data token diambil dari test_data.json (hasilkan dulu:
|
|
python content_parser.py --content-dir ../../content --num-tokens 50
|
|
→ token sintetis LOCUST_TEST_* di-seed ke PostgreSQL bila DATABASE_URL ter-set)
|
|
|
|
Usage (dari elemes/load-test/):
|
|
locust -f locustfile_db.py
|
|
→ set host ke URL Elemes (mis. https://sinau-c-dev.manakin-gentoo.ts.net)
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
import random
|
|
from pathlib import Path
|
|
|
|
from locust import HttpUser, between, events, task
|
|
|
|
TEST_DATA_FILE = Path(__file__).parent / 'test_data.json'
|
|
API = os.environ.get('API_PREFIX', '/api')
|
|
|
|
|
|
def load_test_data() -> dict:
|
|
if not TEST_DATA_FILE.exists():
|
|
raise FileNotFoundError(
|
|
f'{TEST_DATA_FILE} tidak ada. Jalankan: python content_parser.py'
|
|
)
|
|
with open(TEST_DATA_FILE, 'r', encoding='utf-8') as f:
|
|
return json.load(f)
|
|
|
|
|
|
try:
|
|
TEST_DATA = load_test_data()
|
|
except FileNotFoundError as e:
|
|
logging.error(str(e))
|
|
TEST_DATA = {'tokens': [], 'teacher_token': '', 'lessons': []}
|
|
|
|
STUDENT_TOKENS = [t for t in TEST_DATA.get('tokens', []) if t != TEST_DATA.get('teacher_token')]
|
|
TEACHER_TOKEN = TEST_DATA.get('teacher_token', '')
|
|
LESSON_SLUGS = [l['filename'].replace('.md', '') for l in TEST_DATA.get('lessons', [])]
|
|
|
|
if not STUDENT_TOKENS:
|
|
logging.warning('test_data.json tidak punya token siswa — hanya teacher')
|
|
|
|
|
|
class StudentUser(HttpUser):
|
|
"""Siswa: login → baca lesson → track progress (random status)."""
|
|
|
|
wait_time = between(1, 4)
|
|
|
|
def on_start(self):
|
|
self.token = random.choice(STUDENT_TOKENS) if STUDENT_TOKENS else ''
|
|
if not self.token:
|
|
return
|
|
self.client.post(f'{API}/login', json={'token': self.token})
|
|
|
|
@task(2)
|
|
def validate_token(self):
|
|
self.client.post(f'{API}/validate-token', json={'token': self.token})
|
|
|
|
@task(3)
|
|
def read_lesson(self):
|
|
if not LESSON_SLUGS:
|
|
return
|
|
slug = random.choice(LESSON_SLUGS)
|
|
self.client.get(f'/bab/dasar-pemrograman/{slug}', name='/bab/.../{slug}')
|
|
|
|
@task(3)
|
|
def track_progress(self):
|
|
if not LESSON_SLUGS:
|
|
return
|
|
slug = random.choice(LESSON_SLUGS)
|
|
status = random.choice(['completed', 'not_started', '3/4', '2/5'])
|
|
self.client.post(
|
|
f'{API}/track-progress',
|
|
json={'token': self.token, 'lesson_name': slug, 'status': status},
|
|
)
|
|
|
|
|
|
class TeacherUser(HttpUser):
|
|
"""Guru: login → report keseluruhan (beban baca berat di PG)."""
|
|
|
|
wait_time = between(3, 8)
|
|
|
|
def on_start(self):
|
|
if TEACHER_TOKEN:
|
|
self.client.post(f'{API}/login', json={'token': TEACHER_TOKEN})
|
|
|
|
@task(1)
|
|
def progress_report(self):
|
|
if TEACHER_TOKEN:
|
|
self.client.get(f'{API}/progress-report.json?token={TEACHER_TOKEN}')
|
|
|
|
@task(1)
|
|
def export_csv(self):
|
|
if TEACHER_TOKEN:
|
|
self.client.get(f'{API}/progress-report/export-csv?token={TEACHER_TOKEN}')
|