Load Testing Modern dengan K6: Menguji Batas Aplikasi Web Anda Secara Scriptable dan Efisien
Pernahkah Anda bertanya-tanya, “Apakah aplikasi saya siap menghadapi lonjakan trafik saat promo besar atau saat fitur baru diluncurkan?” Atau, “Berapa banyak pengguna yang bisa dilayani aplikasi saya sebelum mulai melambat?” Pertanyaan-pertanyaan ini adalah inti dari load testing, sebuah praktik krusial dalam pengembangan perangkat lunak modern.
Sebagai developer, kita sering fokus pada fungsionalitas dan unit testing. Namun, mengabaikan performa di bawah beban dapat berakibat fatal: aplikasi lambat, error, atau bahkan down. 📉 Ini bukan hanya merugikan reputasi, tapi juga potensi pendapatan dan kepercayaan pengguna.
Dulu, load testing seringkali terasa rumit, membutuhkan setup yang kompleks, tool yang mahal, atau bahkan tim khusus. Namun, di era “developer experience” yang semakin baik, munculah tool-tool modern yang mengubah lanskap ini. Salah satunya adalah K6.
K6 adalah game-changer. Ia membawa revolusi pada load testing dengan pendekatan scriptable dan developer-friendly. Jika Anda sudah terbiasa menulis kode untuk unit test atau e2e test, Anda akan merasa nyaman dengan K6. Artikel ini akan membawa Anda menyelam ke dunia K6, memahami mengapa ia berbeda, dan bagaimana Anda bisa menggunakannya untuk membuat aplikasi web Anda lebih tangguh.
Mari kita mulai perjalanan ini! 🚀
1. Apa itu K6 dan Mengapa Berbeda?
K6 adalah load testing tool open-source yang dikembangkan oleh Grafana Labs. Alih-alih mengandalkan GUI yang kompleks atau konfigurasi XML/JSON yang panjang, K6 memungkinkan Anda menulis skrip pengujian menggunakan JavaScript (atau TypeScript). Ini adalah perbedaan fundamental yang signifikan:
- Code-first Approach: Sebagai developer, Anda sudah familiar dengan kode. Menulis test skrip dalam JavaScript terasa lebih natural dan fleksibel daripada mengklik tombol di GUI atau mengedit file konfigurasi. Ini juga memungkinkan version control yang lebih baik dan integrasi CI/CD yang mulus.
- Performa Tinggi: K6 dibangun dengan Go, yang memberikannya performa luar biasa dalam menghasilkan beban tinggi. Ini berarti K6 dapat mensimulasikan ribuan, bahkan jutaan, Virtual Users (VU) dengan efisien dari satu mesin.
- Built for Automation: K6 didesain untuk diintegrasikan ke dalam pipeline CI/CD Anda. Anda bisa menjalankan tes secara otomatis di setiap commit atau pull request, memastikan performa tetap optimal seiring waktu.
- Metrik Komprehensif: K6 mengumpulkan berbagai metrik performa (response time, throughput, error rate, dll.) dan memungkinkan Anda menetapkan threshold yang akan membuat tes gagal jika performa di bawah standar yang diharapkan.
Analogi Sederhana: Bayangkan Anda ingin menguji kekuatan sebuah jembatan.
- Load testing tradisional (GUI-based): Anda harus menyewa operator crane, mengarahkan crane secara manual, dan mencatat secara manual berapa beban yang bisa ditahan jembatan sebelum retak. Prosesnya lambat, rentan kesalahan manusia, dan sulit diulang persis sama.
- K6 (scriptable): Anda bisa menulis program yang secara otomatis mengirimkan truk-truk dengan beban tertentu ke jembatan, menghitung secara akurat berapa beban maksimum, dan bahkan memberi tahu Anda jika jembatan mulai retak di bawah standar yang Anda tetapkan. Program ini bisa Anda jalankan kapan saja, berulang kali, dengan hasil yang konsisten.
2. Instalasi dan Uji Coba Pertama dengan K6
Memulai K6 sangat mudah. Anda bisa menginstalnya di berbagai sistem operasi.
Instalasi (Contoh untuk macOS dengan Homebrew):
brew install k6
Untuk Linux (Debian/Ubuntu):
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491E1CE65D6
echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt update
sudo apt install k6
Untuk Windows (dengan Chocolatey):
choco install k6
Setelah terinstal, Anda bisa memverifikasinya:
k6 version
✅ Anda akan melihat versi K6 yang terinstal.
Sekarang, mari buat skrip uji coba pertama kita. Buat file bernama basic_test.js:
// basic_test.js
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
http.get('https://test.k6.io'); // Mengirim permintaan GET ke URL ini
sleep(1); // Menunggu 1 detik sebelum iterasi berikutnya
}
Skrip ini sangat sederhana: setiap “virtual user” (VU) akan mengirim permintaan GET ke https://test.k6.io dan kemudian “tidur” selama 1 detik.
Untuk menjalankan tes ini dengan 1 Virtual User selama 10 iterasi:
k6 run --vus 1 --iterations 10 basic_test.js
Anda akan melihat output di terminal yang menunjukkan metrik performa seperti http_req_duration, http_req_failed, dan lainnya. Ini adalah dasar dari K6!
3. Memahami Skrip K6: VU, Iterasi, dan Metrik
Untuk membuat tes yang lebih berarti, kita perlu memahami konsep inti K6:
- Virtual Users (VUs): Ini adalah jumlah pengguna simultan yang akan mensimulasikan interaksi dengan aplikasi Anda. Setiap VU menjalankan skrip test secara independen.
- Iterasi: Setiap kali sebuah VU menyelesaikan eksekusi skrip
default function, itu dihitung sebagai satu iterasi. - Options: Objek
optionsdalam skrip K6 memungkinkan Anda mengontrol bagaimana tes akan berjalan, termasuk jumlah VU, durasi tes, dan lainnya.
Mari kita buat skrip yang lebih lengkap dengan options, checks, dan thresholds.
// advanced_test.js
import http from 'k6/http';
import { sleep, check } from 'k6';
import { Counter, Rate } from 'k6/metrics';
// 💡 Definisikan options untuk mengontrol beban test
export let options = {
vus: 10, // 10 Virtual Users
duration: '30s', // Test akan berjalan selama 30 detik
thresholds: {
// ⚠️ Pastikan 99% dari semua permintaan HTTP memiliki durasi di bawah 500ms
'http_req_duration{expected_response:true}': ['p(99)<500'],
// ⚠️ Pastikan tingkat kegagalan HTTP (status >= 400) kurang dari 1%
'http_req_failed': ['rate<0.01'],
// ✅ Memastikan status kode 200 untuk home page tidak pernah gagal
'checks': ['rate>0.99'],
},
};
// Custom metrics
const myErrors = new Counter('my_custom_errors');
const myErrorRate = new Rate('my_custom_error_rate');
export default function () {
// 🎯 Skenario: Mengakses halaman utama
let res = http.get('https://test.k6.io/');
// ✅ Melakukan check: Memastikan status kode adalah 200 dan body mengandung teks tertentu
check(res, {
'status is 200': (r) => r.status === 200,
'body contains "Welcome"': (r) => r.body.includes('Welcome'),
});
if (res.status >= 400) {
myErrors.add(1);
myErrorRate.add(true);
} else {
myErrorRate.add(false);
}
// 😴 Menunggu secara acak antara 1 hingga 3 detik untuk mensimulasikan perilaku pengguna
sleep(Math.random() * 2 + 1);
}
Penjelasan:
options: Kita mengatur 10 VU yang akan berjalan selama 30 detik.thresholds: Ini adalah Service Level Agreement (SLA) Anda.'http_req_duration{expected_response:true}': ['p(99)<500']berarti 99% dari semua permintaan HTTP yang berhasil harus selesai dalam waktu kurang dari 500 milidetik. Jika tidak, tes akan ditandai sebagaiFAILED.'http_req_failed': ['rate<0.01']berarti tingkat permintaan HTTP yang gagal (misalnya, status kode 4xx atau 5xx) harus kurang dari 1%.'checks': ['rate>0.99']memastikan bahwa lebih dari 99% daricheckyang kita definisikan berhasil.
check(): Fungsi ini memungkinkan Anda memvalidasi respons dari server. Misalnya, memastikan status kode 200 atau konten tertentu ada di body respons. Jikacheckgagal, itu tidak berarti tes secara keseluruhan gagal, tetapi metrikchecksakan mencerminkan kegagalan tersebut.- Custom Metrics: K6 juga memungkinkan Anda membuat metrik kustom sendiri, seperti
myErrorsdanmyErrorRate, untuk melacak hal-hal spesifik dalam skrip Anda. sleep(): Penting untuk mensimulasikan perilaku pengguna yang realistis. Pengguna tidak akan terus-menerus mengirim permintaan tanpa jeda.
Jalankan skrip ini:
k6 run advanced_test.js
Jika salah satu threshold terlampaui, K6 akan menampilkan status FAILED di akhir laporan, yang sangat berguna untuk CI/CD.
4. Skenario Uji yang Lebih Realistis: Login dan CRUD API
Untuk aplikasi yang lebih kompleks, Anda perlu mensimulasikan alur pengguna yang berurutan. Misalnya, pengguna login, lalu mengambil daftar produk, dan mungkin menambahkan item ke keranjang.
// api_workflow_test.js
import http from 'k6/http';
import { sleep, check } from 'k6';
import { SharedArray } from 'k6/data'; // Untuk data parameterisasi
// Data pengguna dari JSON file
const users = new SharedArray('users', function () {
return JSON.parse(open('./users.json')).users;
});
export let options = {
stages: [
{ duration: '10s', target: 5 }, // Naikkan ke 5 VU dalam 10 detik
{ duration: '30s', target: 5 }, // Tetap di 5 VU selama 30 detik
{ duration: '10s', target: 0 }, // Turunkan ke 0 VU dalam 10 detik
],
thresholds: {
'http_req_duration{name:Login}': ['p(95)<200'], // 95% login di bawah 200ms
'http_req_duration{name:GetProducts}': ['p(95)<300'], // 95% get products di bawah 300ms
'http_req_failed': ['rate<0.01'],
},
};
export default function () {
// Ambil user dari SharedArray secara acak untuk setiap VU
const user = users[Math.floor(Math.random() * users.length)];
// 1. Skenario Login
let loginRes = http.post(
'https://api.example.com/login', // Ganti dengan URL login API Anda
JSON.stringify({ username: user.username, password: user.password }),
{
headers: { 'Content-Type': 'application/json' },
tags: { name: 'Login' }, // Tagging request untuk metrik spesifik
}
);
check(loginRes, {
'login status is 200': (r) => r.status === 200,
'login successful': (r) => r.json().token !== undefined,
});
const authToken = loginRes.json().token;
if (authToken) {
// 2. Skenario Ambil Daftar Produk (membutuhkan autentikasi)
let productsRes = http.get(
'https://api.example.com/products', // Ganti dengan URL produk API Anda
{
headers: { Authorization: `Bearer ${authToken}` },
tags: { name: 'GetProducts' },
}
);
check(productsRes, {
'get products status is 200': (r) => r.status === 200,
'products list is not empty': (r) => r.json().length > 0,
});
// 3. Skenario Tambah Item ke Keranjang (contoh POST request)
const productId = productsRes.json()[0]?.id; // Ambil ID produk pertama
if (productId) {
let addCartRes = http.post(
'https://api.example.com/cart/add', // Ganti dengan URL add cart API Anda
JSON.stringify({ productId: productId, quantity: 1 }),
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${authToken}`,
},
tags: { name: 'AddToCart' },
}
);
check(addCartRes, {
'add to cart status is 200': (r) => r.status === 200,
'item added to cart': (r) => r.json().success === true,
});
}
}
// 😴 Jeda antar iterasi
sleep(2);
}
Dan buat file users.json:
{
"users": [
{ "username": "user1", "password": "password1" },
{ "username": "user2", "password": "password2" },
{ "username": "user3", "password": "password3" }
]
}
Poin Penting:
SharedArray: Digunakan untuk memuat data dari file (misalnya data pengguna) sekali di awal tes, dan kemudian membagikannya ke semua VU. Ini menghindari overhead pembacaan file berulang kali.stages: Ini adalah cara untuk mendefinisikan “profil beban” dari tes Anda. Di contoh ini, kita secara bertahap menaikkan VU, mempertahankannya, lalu menurunkannya. Ini sangat berguna untuk mensimulasikan lonjakan trafik realistis.tags: Dengan menambahkantagspada request, Anda bisa mendapatkan metrik performa yang lebih spesifik untuk setiap jenis request (misalnya,http_req_duration{name:Login}). Ini memudahkan identifikasi bottleneck.- Mengelola State: Dalam skenario login, kita mengambil
authTokendari respons login dan menggunakannya untuk permintaan berikutnya. Ini mensimulasikan alur pengguna yang sebenarnya.
Untuk menjalankan tes ini:
k6 run api_workflow_test.js
5. Integrasi CI/CD dan Observabilitas
Salah satu kekuatan terbesar K6 adalah kemampuannya untuk diintegrasikan dengan mudah ke dalam pipeline CI/CD. Dengan thresholds, Anda bisa memastikan bahwa setiap perubahan kode tidak menurunkan performa aplikasi.
Contoh GitHub Actions:
# .github/workflows/k6-load-test.yml
name: K6 Load Test
on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch: # Memungkinkan trigger manual
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install k6
run: sudo apt-get update && sudo apt-get install k6
- name: Run k6 load test
run: k6 run --out json=result.json advanced_test.js # Ganti dengan skrip test Anda
# Jika ada threshold yang gagal, action akan gagal
Dengan konfigurasi ini, setiap kali ada pull request atau push ke branch main, tes K6 akan berjalan otomatis. Jika metrik performa Anda melampaui threshold yang ditentukan, pipeline akan gagal, memberikan umpan balik instan kepada developer. ❌
Observabilitas Lebih Lanjut: K6 dapat mengekspor hasilnya ke berbagai format dan platform, termasuk:
- JSON: Untuk analisis lebih lanjut.
- InfluxDB, Prometheus: Untuk penyimpanan metrik jangka panjang.
- Grafana: Untuk visualisasi data yang indah dan dashboard interaktif.
- K6 Cloud: Layanan berbayar dari Grafana Labs yang memungkinkan Anda menjalankan tes skala besar dari berbagai lokasi geografis, memantau secara real-time, dan menyimpan riwayat tes.
Integrasi dengan Grafana, misalnya, memungkinkan Anda membuat dashboard khusus yang menampilkan metrik K6 berdampingan dengan metrik APM (Application Performance Monitoring) lainnya, memberikan gambaran holistik tentang kesehatan dan performa aplikasi Anda.
Kesimpulan
K6 telah merevolusi cara kita melakukan load testing. Dengan pendekatan code-first dan scriptable menggunakan JavaScript, ia memberdayakan developer untuk mengambil kendali penuh atas pengujian performa. Dari simulasi alur pengguna yang kompleks hingga integrasi mulus dengan pipeline CI/CD, K6 memastikan bahwa performa tidak lagi menjadi afterthought, melainkan bagian integral dari siklus pengembangan Anda.
Mulai sekarang, Anda tidak perlu lagi khawatir tentang aplikasi Anda yang “melempem” di bawah beban. Dengan K6, Anda bisa menguji, mengukur, dan memastikan aplikasi Anda siap menghadapi tantangan di dunia nyata. Ini adalah investasi kecil yang akan memberikan dampak besar pada keandalan dan skalabilitas aplikasi Anda.
Jadi, tunggu apa lagi? Mulailah petualangan load testing Anda dengan K6 hari ini! 🚀
🔗 Baca Juga
- Performance Testing Aplikasi Web: Menguji Batas Skalabilitas dan Stabilitas Sistem Anda
- CI/CD untuk Proyek Backend Modern — Dari Git Push hingga Produksi
- Application Performance Monitoring (APM): Mengungkap Kinerja Aplikasi Anda secara Menyeluruh
- Menguasai Core Web Vitals: Strategi Praktis untuk Performa Web yang Unggul