LOAD-TESTING PERFORMANCE-TESTING K6 DEVOPS CI-CD WEB-PERFORMANCE BACKEND FRONTEND JAVASCRIPT AUTOMATION SCALABILITY RELIABILITY API-TESTING SYSTEM-DESIGN

Load Testing Modern dengan K6: Menguji Batas Aplikasi Web Anda Secara Scriptable dan Efisien

⏱️ 12 menit baca
👨‍💻

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:

Analogi Sederhana: Bayangkan Anda ingin menguji kekuatan sebuah jembatan.

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:

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:

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:

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:

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