/** * EN: k6 load test — Order creation endpoint (POST /api/v1/orders). * VI: k6 load test — endpoint tạo đơn hàng (POST /api/v1/orders). * * Usage: * k6 run tests/load/k6/order-creation.js * k6 run --env BASE_URL=http://api.staging.goodgo.vn tests/load/k6/order-creation.js * * Thresholds: * - 95th-percentile response time < 500ms * - Error rate < 1% */ import http from 'k6/http'; import { check, sleep } from 'k6'; import { Rate, Trend } from 'k6/metrics'; // --------------------------------------------------------------------------- // Custom metrics // --------------------------------------------------------------------------- const orderCreationErrors = new Rate('order_creation_errors'); const orderCreationDuration = new Trend('order_creation_duration', true); // --------------------------------------------------------------------------- // Test options // --------------------------------------------------------------------------- export const options = { stages: [ // EN: Ramp up to 20 VUs over 30s / VI: Tăng lên 20 VUs trong 30s { duration: '30s', target: 20 }, // EN: Hold at 20 VUs for 1 minute / VI: Duy trì 20 VUs trong 1 phút { duration: '1m', target: 20 }, // EN: Spike to 50 VUs for 30s / VI: Tăng đột biến lên 50 VUs trong 30s { duration: '30s', target: 50 }, // EN: Ramp down / VI: Giảm dần { duration: '30s', target: 0 }, ], thresholds: { // EN: 95% of requests must complete below 500ms / VI: 95% requests phải hoàn thành dưới 500ms http_req_duration: ['p(95)<500'], // EN: Error rate must stay below 1% / VI: Tỷ lệ lỗi phải dưới 1% order_creation_errors: ['rate<0.01'], // EN: Custom trend threshold / VI: Ngưỡng trend tùy chỉnh order_creation_duration: ['p(99)<1000'], }, }; // --------------------------------------------------------------------------- // Config // --------------------------------------------------------------------------- const BASE_URL = __ENV.BASE_URL || 'http://localhost:5010'; const JWT_TOKEN = __ENV.JWT_TOKEN || 'test-bearer-token'; const SHOP_ID = __ENV.SHOP_ID || '00000000-0000-0000-0000-000000000001'; const PRODUCT_ID = __ENV.PRODUCT_ID || '00000000-0000-0000-0000-000000000002'; const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${JWT_TOKEN}`, 'X-Shop-Id': SHOP_ID, }; // --------------------------------------------------------------------------- // Helper — generate a random order payload // --------------------------------------------------------------------------- function buildOrderPayload() { const tableNumber = Math.floor(Math.random() * 20) + 1; const qty = Math.floor(Math.random() * 3) + 1; return JSON.stringify({ shopId: SHOP_ID, tableNumber: `T${tableNumber}`, orderType: 'dine_in', items: [ { productId: PRODUCT_ID, quantity: qty, unitPrice: 35000, note: '', }, ], note: `k6-load-test-${Date.now()}`, }); } // --------------------------------------------------------------------------- // Default function — executed per VU iteration // --------------------------------------------------------------------------- export default function () { const payload = buildOrderPayload(); const startTime = Date.now(); const res = http.post(`${BASE_URL}/api/v1/orders`, payload, { headers }); const duration = Date.now() - startTime; orderCreationDuration.add(duration); const success = check(res, { // EN: Status is 201 Created / VI: Status là 201 Created 'status is 201': (r) => r.status === 201, // EN: Response body has success=true / VI: Body phản hồi có success=true 'body has success:true': (r) => { try { return JSON.parse(r.body).success === true; } catch { return false; } }, // EN: Response time below 500ms / VI: Thời gian phản hồi dưới 500ms 'response time < 500ms': (r) => r.timings.duration < 500, }); if (!success) { orderCreationErrors.add(1); } else { orderCreationErrors.add(0); } // EN: Think time between requests (0.5–1.5s) / VI: Thời gian nghỉ giữa các request sleep(0.5 + Math.random()); }