236 lines
9.5 KiB
Bash

#!/bin/bash
# ═══════════════════════════════════════════════════════════════════════════
# WalkGuide — k6 Test Runner
# Jalankan semua k6 scenarios secara berurutan atau individual.
#
# Usage:
# chmod +x run-all-tests.sh
# ./run-all-tests.sh [mode] [BASE_URL]
#
# Modes:
# smoke — 10 VUs, 1 menit (quick sanity check)
# load — 50 VUs, 5 menit (normal production load, WAJIB untuk exam)
# stress — 100 VUs, 10 menit (breaking point)
# spike — 0→200 VUs sudden spike
# all — jalankan smoke → load → stress → spike berurutan
# auth — hanya auth-flow.js
# pairing — hanya pairing-flow.js
# location — hanya location-update.js
# obstacle — hanya obstacle-logging.js
# sos — hanya sos-flow.js
# notif — hanya notification-send.js
# timeline — hanya timeline-query.js
#
# Contoh:
# ./run-all-tests.sh load http://202.46.28.160:8080
# ./run-all-tests.sh smoke
# ./run-all-tests.sh all http://202.46.28.160:8080
# ═══════════════════════════════════════════════════════════════════════════
set -e
# ── Config ────────────────────────────────────────────────────────────────────
MODE="${1:-load}"
BASE_URL="${2:-http://202.46.28.160:8080}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
RESULTS_DIR="${SCRIPT_DIR}/k6-results"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# ── Colors ────────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# ── Helpers ───────────────────────────────────────────────────────────────────
log() { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $1"; }
ok() { echo -e "${GREEN}[✅ OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[⚠️ WARN]${NC} $1"; }
err() { echo -e "${RED}[❌ ERR]${NC} $1"; }
hr() { echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"; }
# ── Pre-flight checks ─────────────────────────────────────────────────────────
hr
echo -e "${BOLD} 🦺 WalkGuide — k6 Load Test Runner${NC}"
echo -e " Mode: ${YELLOW}${MODE}${NC} | Backend: ${YELLOW}${BASE_URL}${NC}"
hr
# Check k6 installed
if ! command -v k6 &> /dev/null; then
err "k6 not installed!"
echo "Install: https://k6.io/docs/getting-started/installation/"
echo "Ubuntu: sudo apt-get install k6"
echo "Mac: brew install k6"
echo "Docker: docker run grafana/k6 run ..."
exit 1
fi
K6_VERSION=$(k6 version 2>&1 | head -1)
ok "k6 found: $K6_VERSION"
# Check Node.js (for result parsing)
if command -v node &> /dev/null; then
ok "Node.js: $(node --version)"
else
warn "Node.js not found — skipping HTML report generation"
fi
# Create results dir
mkdir -p "$RESULTS_DIR"
ok "Results dir: $RESULTS_DIR"
# ── Backend reachability check ────────────────────────────────────────────────
log "Checking backend reachability..."
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${BASE_URL}/api/v1/auth/ping" --max-time 10 2>/dev/null || echo "000")
if [ "$HTTP_STATUS" = "200" ]; then
ok "Backend reachable (HTTP $HTTP_STATUS)"
elif [ "$HTTP_STATUS" = "000" ]; then
warn "Backend not reachable or timeout. Continuing anyway (tests will fail gracefully)."
else
warn "Backend returned HTTP $HTTP_STATUS. Continuing..."
fi
# ── k6 run helper ─────────────────────────────────────────────────────────────
run_k6() {
local scenario_file="$1"
local scenario_name="$2"
local extra_args="${3:-}"
local output_json="${RESULTS_DIR}/${scenario_name}_${TIMESTAMP}.ndjson"
local summary_json="${RESULTS_DIR}/${scenario_name}_summary_${TIMESTAMP}.json"
log "Running scenario: ${BOLD}${scenario_name}${NC}"
log "Script: ${scenario_file}"
local k6_cmd="k6 run \
--out json=${output_json} \
-e BASE_URL=${BASE_URL} \
--summary-export=${summary_json} \
--no-color \
${extra_args} \
${SCRIPT_DIR}/scenarios/${scenario_file}"
echo "Command: $k6_cmd"
hr
if eval "$k6_cmd"; then
ok "Scenario ${scenario_name} completed successfully"
else
warn "Scenario ${scenario_name} completed with threshold violations (check results)"
fi
# Parse results if Node.js available
if command -v node &> /dev/null && [ -f "$output_json" ]; then
log "Parsing results..."
local parsed_json="${RESULTS_DIR}/${scenario_name}_parsed_${TIMESTAMP}.json"
local html_report="${RESULTS_DIR}/${scenario_name}_report_${TIMESTAMP}.html"
node "${SCRIPT_DIR}/utils/result-parser.js" "$output_json" "$parsed_json" 2>/dev/null || true
node "${SCRIPT_DIR}/utils/html-reporter.js" "$parsed_json" "$html_report" 2>/dev/null || true
if [ -f "$html_report" ]; then
ok "HTML report: $html_report"
fi
fi
echo ""
}
# ── Stage-specific k6 args ────────────────────────────────────────────────────
SMOKE_ARGS="--stage 30s:3 --stage 60s:10 --stage 30s:0"
# Note: --stage shorthand diganti inline di script JSON
# ── Test execution ─────────────────────────────────────────────────────────────
case "$MODE" in
smoke)
log "=== SMOKE TEST (10 VUs, 1 min) ==="
run_k6 "auth-flow.js" "smoke_auth" "--vus 3 --duration 60s"
run_k6 "location-update.js" "smoke_location" "--vus 3 --duration 60s"
run_k6 "sos-flow.js" "smoke_sos" "--vus 2 --duration 60s"
;;
load)
log "=== LOAD TEST (50+ VUs, 5 min) — EXAM REQUIRED ==="
run_k6 "auth-flow.js" "load_auth"
run_k6 "pairing-flow.js" "load_pairing"
run_k6 "location-update.js" "load_location"
run_k6 "obstacle-logging.js" "load_obstacle"
run_k6 "sos-flow.js" "load_sos"
run_k6 "notification-send.js" "load_notif"
run_k6 "timeline-query.js" "load_timeline"
;;
stress)
log "=== STRESS TEST (100 VUs, 10 min) ==="
run_k6 "location-update.js" "stress_location"
run_k6 "obstacle-logging.js" "stress_obstacle"
run_k6 "notification-send.js" "stress_notif"
run_k6 "timeline-query.js" "stress_timeline"
;;
spike)
log "=== SPIKE TEST (0→200 VUs sudden) ==="
run_k6 "location-update.js" "spike_location"
run_k6 "obstacle-logging.js" "spike_obstacle"
;;
all)
log "=== FULL TEST SUITE (smoke → load → stress → spike) ==="
warn "Estimated total time: 30-45 minutes"
read -p "Continue? [y/N] " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "Aborted."; exit 0
fi
# Smoke
log "--- Phase 1: Smoke Test ---"
run_k6 "auth-flow.js" "fullsuite_smoke_auth" "--vus 3 --duration 60s"
run_k6 "location-update.js" "fullsuite_smoke_location" "--vus 3 --duration 60s"
# Load
log "--- Phase 2: Load Test ---"
run_k6 "auth-flow.js" "fullsuite_load_auth"
run_k6 "location-update.js" "fullsuite_load_location"
run_k6 "obstacle-logging.js" "fullsuite_load_obstacle"
run_k6 "sos-flow.js" "fullsuite_load_sos"
run_k6 "notification-send.js" "fullsuite_load_notif"
run_k6 "timeline-query.js" "fullsuite_load_timeline"
# Stress
log "--- Phase 3: Stress Test ---"
run_k6 "location-update.js" "fullsuite_stress_location"
# Spike
log "--- Phase 4: Spike Test ---"
run_k6 "location-update.js" "fullsuite_spike_location"
;;
# Individual scenarios
auth) run_k6 "auth-flow.js" "individual_auth" ;;
pairing) run_k6 "pairing-flow.js" "individual_pairing" ;;
location) run_k6 "location-update.js" "individual_location" ;;
obstacle) run_k6 "obstacle-logging.js" "individual_obstacle" ;;
sos) run_k6 "sos-flow.js" "individual_sos" ;;
notif) run_k6 "notification-send.js" "individual_notif" ;;
timeline) run_k6 "timeline-query.js" "individual_timeline" ;;
*)
err "Unknown mode: $MODE"
echo "Valid modes: smoke | load | stress | spike | all | auth | pairing | location | obstacle | sos | notif | timeline"
exit 1
;;
esac
# ── Final summary ─────────────────────────────────────────────────────────────
hr
ok "All k6 tests finished!"
log "Results saved to: $RESULTS_DIR"
echo ""
echo "Files generated:"
ls -lh "$RESULTS_DIR"/*.{json,html} 2>/dev/null || echo " (no files found)"
hr