Menguasai k6 secara mendalam: script structure, options dan thresholds, HTTP API load testing, dynamic data, cookies, dan k6 cloud untuk distributed load testing di infrastruktur Grafana.

Setelah di episode 3 kita memahami load testing fundamentals dan menjalankan test pertama, kini saatnya mendalami k6 secara komprehensif. k6 adalah tool load testing utama yang akan kita pakai di sebagian besar series ini — ditulis dalam Go dengan scripting JavaScript, ringan, cepat, dan terintegrasi alami dengan ekosistem observability.
k6 membedakan dirinya dari JMeter dan Locust dengan pendekatan script-first: semua test ditulis dalam JavaScript yang bisa di-version control, di-review, dan diotomasi. Tidak ada GUI yang memakan RAM — hanya binary tunggal yang menjalankan script. Episode ini membawa kalian dari menulis script pertama hingga memahami konsep advanced k6.
Setiap script k6 terdiri dari tiga bagian inti:
options mendefinisikan konfigurasi test: jumlah VUs, durasi, stages, dan thresholds. Ini adalah bagian yang menentukan bagaimana test berjalan.
export const options = {
vus: 50,
duration: '2m',
thresholds: {
http_req_duration: ['p(95)<300'],
http_req_failed: ['rate<0.01'],
},
};setup() dijalankan sekali sebelum test dimulai — cocok untuk mendapatkan authentication token atau data awal. teardown() dijalankan sekali setelah test selesai — cocok untuk cleanup.
export function setup() {
const loginRes = http.post('https://api.example.com/login', JSON.stringify({
username: 'testuser',
password: 'testpass',
}));
return { token: loginRes.json('token') };
}
export default function (data) {
http.get('https://api.example.com/dashboard', {
headers: { Authorization: `Bearer ${data.token}` },
});
}
export function teardown(data) {
// Cleanup setelah test
}Fungsi utama yang dijalankan berulang kali oleh setiap VU. Setiap iterasi adalah satu "user journey" — dari request pertama sampai terakhir dalam script.
Kontrol beban secara dinamis dengan stages:
export const options = {
stages: [
{ duration: '2m', target: 100 }, // Ramp-up 2 menit ke 100 VUs
{ duration: '5m', target: 100 }, // Steady-state 5 menit
{ duration: '2m', target: 200 }, // Naik ke 200 VUs
{ duration: '5m', target: 200 }, // Steady-state di beban tinggi
{ duration: '2m', target: 0 }, // Ramp-down
],
};Thresholds bisa difilter berdasarkan tags — berguna untuk menguji endpoint spesifik:
export const options = {
thresholds: {
'http_req_duration{endpoint:search}': ['p(95)<200'],
'http_req_duration{endpoint:checkout}': ['p(99)<1000'],
'http_req_failed{endpoint:checkout}': ['rate<0.005'],
},
};
export default function () {
const searchRes = http.get('https://api.example.com/search?q=test', {
tags: { endpoint: 'search' },
});
const checkoutRes = http.post('https://api.example.com/checkout', null, {
tags: { endpoint: 'checkout' },
});
}Gunakan rampingVUs untuk auto-scaling VUs berdasarkan tahap test:
export const options = {
scenarios: {
steady_load: {
executor: 'constant-vus',
vus: 50,
duration: '5m',
},
spike_load: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '30s', target: 200 },
{ duration: '30s', target: 0 },
],
},
},
};k6 mendukung semua HTTP methods:
import http from 'k6/http';
export default function () {
// GET
http.get('https://api.example.com/products');
// POST dengan JSON body
http.post('https://api.example.com/products', JSON.stringify({
name: 'Widget',
price: 29.99,
}), { headers: { 'Content-Type': 'application/json' } });
// PUT
http.put('https://api.example.com/products/1', JSON.stringify({
name: 'Updated Widget',
}), { headers: { 'Content-Type': 'application/json' } });
// DELETE
http.del('https://api.example.com/products/1');
}Gunakan check() untuk memvalidasi response — ini menggabungkan functional testing dengan performance testing:
import { check } from 'k6/http';
export default function () {
const res = http.get('https://api.example.com/products');
check(res, {
'status is 200': (r) => r.status === 200,
'has products array': (r) => Array.isArray(r.json()),
'response time < 300ms': (r) => r.timings.duration < 300,
'content-type is JSON': (r) => r.headers['Content-Type']?.includes('application/json'),
});
}Gunakan SharedArray untuk data yang dibagi antar VUs — misal daftar product IDs atau user credentials:
import { SharedArray } from 'k6/data';
const users = new SharedArray('users', function () {
return JSON.parse(open('./users.json'));
});
export default function () {
const user = users[Math.floor(Math.random() * users.length)];
http.get(`https://api.example.com/users/${user.id}`);
}Untuk data yang tidak perlu persisten, gunakan __VU dan __ITER untuk menghasilkan data unik per VU/iterasi:
export default function () {
const payload = JSON.stringify({
userId: `user-${__VU}-${__ITER}`,
timestamp: Date.now(),
});
http.post('https://api.example.com/events', payload, {
headers: { 'Content-Type': 'application/json' },
});
}k6 secara otomatis menyimpan dan mengirim cookies seperti browser. Untuk skenario login:
import http from 'k6/http';
import { check } from 'k6';
export default function () {
// Login - cookies otomatis disimpan
const loginRes = http.post('https://api.example.com/login', JSON.stringify({
username: 'testuser',
password: 'testpass',
}), { headers: { 'Content-Type': 'application/json' } });
// Request berikutnya otomatis menyertakan session cookies
const dashboardRes = http.get('https://api.example.com/dashboard');
check(dashboardRes, {
'dashboard loaded': (r) => r.status === 200,
});
}Untuk JWT, simpan token di variable dan kirim manual di headers:
let token;
export function setup() {
const res = http.post('https://api.example.com/auth', JSON.stringify({
username: 'testuser',
password: 'testpass',
}));
token = res.json('accessToken');
}
export default function () {
http.get('https://api.example.com/protected', {
headers: { Authorization: `Bearer ${token}` },
});
}k6 Cloud adalah platform hosted dari Grafana Labs untuk distributed load testing — menghapus kebutuhan infrastructure management sendiri.
# Jalankan test di k6 Cloud
k6 cloud script.js
# Login ke k6 Cloud (opsional, untuk CI/CD)
k6 login cloudKalian memerlukan akun Grafana Cloud untuk menggunakan k6 Cloud. Untuk sementara, binary k6 lokal sudah cukup untuk seluruh episode berikutnya.
Di episode 4 ini kalian telah menguasai k6 secara komprehensif:
Di episode 5 selanjutnya, kita akan membandingkan k6 dengan JMeter dan Locust — memahami kapan menggunakan masing-masing tool, kelebihan dan kekurangan, serta skenario yang paling cocok untuk setiap tool.