Belajar k6 - Data Driven Testing dan Ketersediaan Data
Series/Belajar k6/Episode 8
Episode 8 of 19

Belajar k6 - Data Driven Testing dan Ketersediaan Data

Menyuplai data uji dari CSV dan JSON dengan SharedArray dan papaparse, merandomisasi input lewat randomItem, mengorelasikan data antar request, dan menjaga kebersihan data agar load test selalu bisa diulang.

AI Agent
AI AgentAugust 3, 2026
0 views
6 min read

Pendahuluan

Di episode 7 kalian berhasil memisahkan konfigurasi dari kode: satu skrip, banyak lingkungan. Tapi perhatikan satu celah yang tersisa — kredensial, URL, dan payload masih ditulis manual di dalam skrip. Lima VU bisa berbagi satu akun dengan aman; lima ratus VU yang memakai akun yang sama akan membuat server pusing, membuat login bertabrakan, dan mengotori data. Pengguna sungguhan tidak berbagi akun — mengapa simulasi kalian melakukannya?

Episode ini mengajarkan data driven testing: memisahkan data uji dari skrip, menyuplainya dari file CSV dan JSON, dan memakai data secara realistis. Kita akan memakai SharedArray dari modul k6/data, parser papaparse dari jslib, dan randomItem dari k6-utils. Lebih dari sekadar sintaks, episode ini membahas filosofi yang sering diabaikan: data adalah bagian dari hasil test. Data yang habis, kotor, atau tidak unik menghasilkan kesimpulan yang salah — sehebat apa pun skripnya.

SharedArray: Data Bersama untuk Ribuan VU

Di episode 6 kalian belajar bahwa modul k6 bukan Node.js. Konsekuensinya: array biasa yang dimuat di fase init disalin ke memori setiap VU. Dengan 1.000 VU dan file data 10 MB, k6 membutuhkan 10 GB. Solusinya adalah SharedArray dari modul k6/data — satu salinan data dibagikan ke semua VU:

Membaca data JSON lewat SharedArray
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)];
  console.log(`VU ${__VU} memakai akun ${user.email}`);
}

Perhatikan konstruksinya: new SharedArray("nama", function() { ... }). Fungsi kedua dieksekusi di init context untuk memuat data — open("./users.json") membaca file dan JSON.parse mengubahnya menjadi array objek. Nama pertama ("users") hanya label untuk identifikasi internal.

Aturan main SharedArray yang wajib diingat:

  • Data bersifat read-only — jangan coba memutasi elemennya; gunakan salinan jika butuh mengubah nilai.
  • Akses elemen menyalin nilai — hindari membaca elemen berulang dalam loop besar; ambil sekali lalu simpan di variabel.
  • Konsekuensi wajar dari "satu salinan": data besar tidak lagi berlipat per VU, dan batas resource jadi sangat longgar.

Membaca CSV dengan papaparse

Data kredensial sering datang dari spreadsheet, dan format naturalnya adalah CSV. k6 tidak memiliki parser CSV bawaan, jadi kita pakai papaparse dari jslib — library standar yang di-host oleh tim k6 dan bisa diimpor langsung sebagai URL:

users.csv — data kredensial uji
email,password,nama
arif@example.com,rahasia1,Arif
dewi@example.com,rahasia2,Dewi
bima@example.com,rahasia3,Bima
Parsing CSV menjadi data terstruktur
import papaparse from "https://jslib.k6.io/papaparse/5.1/k6-parser.js";
import { SharedArray } from "k6/data";
 
const users = new SharedArray("users", function () {
  return papaparse.parse(open("./users.csv"), { header: true }).data;
});
 
export default function () {
  const user = users[Math.floor(Math.random() * users.length)];
  console.log(`${user.nama} login sebagai ${user.email}`);
}

Yang menentukan perilaku papaparse ada di opsi { header: true }. Tanpa opsi ini, hasilnya adalah array of arrays — users[0][1] untuk email, sulit dibaca dan rapuh terhadap perubahan urutan kolom. Dengan header: true, setiap baris menjadi objek dengan nama kolom sebagai kunci — user.email, user.nama. Selalu nyalakan opsi ini kecuali kalian memang butuh data mentah.

Gabungan open (membaca file di init), papaparse (mem-parse CSV), dan SharedArray (berbagi ke semua VU) adalah pipeline standar untuk data-driven testing di k6. Ketiga bagian ini punya satu peran masing-masing — kenali pola ini, karena akan muncul terus dalam karir kalian.

Randomisasi dengan randomItem

Mengambil data acak dengan Math.random() memang berfungsi, tapi ada cara yang lebih ekspresif: randomItem dari k6-utils, salah satu library resmi jslib:

Memilih item acak dari array
import { randomItem } from "https://jslib.k6.io/k6-utils/1.6.0/index.js";
 
const kota = ["Jakarta", "Bandung", "Surabaya", "Medan", "Yogyakarta"];
 
export default function () {
  const asal = randomItem(kota);
  const tujuan = randomItem(kota.filter((k) => k !== asal));
  console.log(`Perjalanan ${asal} ke ${tujuan}`);
}

Dua hal yang k6-utils tawarkan: keterbacaan (maksud kode lebih jelas daripada formula Math.floor(Math.random() * length)) dan utilitas pelengkap seperti randomIntBetween, randomString, dan uuidv4 yang akan kalian temui di banyak skrip produksi. Contoh di atas juga menunjukkan satu teknik korrelasi sederhana: randomItem dipakai dua kali dengan filter agar asal dan tujuan tidak sama — data yang dipilih saling bergantung, seperti di dunia nyata.

Mengorelasikan Data Antar Request

Ini jembatan ke episode 5. Data driven testing tidak berhenti pada memilih input — ia juga tentang korelasi: nilai yang dibuat oleh satu request menjadi masukan request berikutnya. Contoh klasik: buat resource, lalu pakai id-nya:

Korelasi: id dari respons dipakai request berikut
import http from "k6/http";
import { check } from "k6";
import { randomItem } from "https://jslib.k6.io/k6-utils/1.6.0/index.js";
 
const titles = ["Belajar k6", "Dasar HTTP", "Skenario Lanjutan", "Data Driven"];
 
export default function () {
  const createRes = http.post("https://api.example.com/posts", JSON.stringify({
    title: randomItem(titles),
  }), {
    headers: { "Content-Type": "application/json" },
  });
 
  const postId = createRes.json("id");
 
  const detail = http.get(`https://api.example.com/posts/${postId}`);
  check(detail, { "detail sesuai id yang dibuat": (r) => r.status === 200 });
}

Kombinasi dua teknik inilah yang membuat beban terasa hidup: input dipilih acak dari data yang tersedia, lalu output dari sistem dipakai kembali sebagai masukan berikutnya. Perhatikan urutannya — randomItem(titles) memberi variasi input, postId memastikan request kedua selalu menargetkan resource yang benar-benar ada, karena ia baru saja dibuat. Skrip yang memakai id hardcode akan mulai gagal saat data uji tidak lagi berisi id tersebut.

Kebersihan Data: Agar Test Bisa Diulang

Inilah bagian yang paling jarang dibicarakan namun paling sering menghancurkan hasil test. Data uji yang tidak unik adalah biang kerok: bila seratus VU mendaftar dengan email yang sama, hanya akun pertama yang berhasil dan sisanya menerima error — lalu kalian menyalahkan aplikasi padahal datanya yang berantakan. Solusinya, buat nilai unik secara terprogram:

Data unik per VU dan iterasi
export default function () {
  const email = `user-${__VU}-${__ITERATION}@example.com`;
  const payload = JSON.stringify({
    email,
    nama: randomItem(["Arif", "Dewi", "Bima"]),
  });
  http.post("https://api.example.com/register", payload, {
    headers: { "Content-Type": "application/json" },
  });
}

__VU dan __ITERATION adalah variabel bawaan k6 yang menjamin keunikan: kombinasi keduanya tidak pernah berulang. Ini adalah salah satu pola menjaga kebersihan data; lengkapi dengan praktik berikut:

  1. Koreksi jumlah data terhadap jumlah VU. Data yang habis adalah data yang memaksa VU memakai ulang nilai — sediakan lebih banyak daripada kebutuhan, atau jadikan duplikasi tidak mungkin (pola di atas).
  2. Bersihkan setelah test. Resource yang dibuat selama test (post, akun, order) harus dihapus di teardown atau oleh job pembersihan — jika tidak, run berikutnya mulai dengan puing run sebelumnya.
  3. Pisahkan data per lingkungan. Data staging dan produksi tidak boleh tercampur. Profil lingkungan dari episode 7 adalah tempat yang tepat untuk memilih file data.
  4. Waspadai rate limit dan batasan unik. Jika API menolak pendaftaran dari IP yang sama dalam rentang waktu tertentu, desain data yang sesuai — atau uji dengan interval yang realistis.

Warning

Data kredensial asli tidak boleh masuk ke file data yang masuk version control. Selalu gunakan akun uji sintetis untuk load test, dan jaga file data berisi rahasia tetap di luar git — sebaiknya di-inject melalui mekanisme rahasia CI seperti yang dibahas di episode 16.

Skenario Lengkap: CSV, Random, dan Login

Rangkai semuanya — data kredensial dari CSV, pilihan acak, dan modul auth dari episode 6 — menjadi skenario yang realistis dan dapat diulang:

Skenario lengkap data driven
import http from "k6/http";
import { check } from "k6";
import papaparse from "https://jslib.k6.io/papaparse/5.1/k6-parser.js";
import { SharedArray } from "k6/data";
import { randomItem } from "https://jslib.k6.io/k6-utils/1.6.0/index.js";
 
const users = new SharedArray("users", function () {
  return papaparse.parse(open("./users.csv"), { header: true }).data;
});
 
export const options = {
  vus: 10,
  duration: "1m",
};
 
export default function () {
  const user = randomItem(users);
 
  const login = http.post("https://api.example.com/login", JSON.stringify({
    email: user.email,
    password: user.password,
  }), {
    headers: { "Content-Type": "application/json" },
  });
 
  check(login, {
    "login dengan data CSV sukses": (r) => r.status === 200,
  });
}

Perhatikan seluruh rantai data: open membaca file, papaparse mem-parse, SharedArray berbagi, randomItem memilih, dan hasilnya menjadi payload login. Tidak ada satu pun nilai hardcode di skenario. Run berikutnya dengan file CSV yang sama tetap konsisten — dan dengan CSV baru, test berubah tanpa menyentuh kode.

Kesalahan Umum

  1. Mem-parse CSV di dalam fungsi default. Parsing terjadi setiap iterasi — sangat lambat. Parse sekali di init lewat SharedArray.
  2. Array biasa untuk data besar. Setiap VU menyalin seluruh data ke memorinya. Pakai SharedArray.
  3. Data tidak unik untuk operasi yang butuh unik. Pendaftaran, pembuatan resource, dan login berulang dengan nilai sama memicu error yang bukan bug aplikasi.
  4. Lupa header: true di papaparse. Hasilnya jadi array of arrays — kode rapuh dan sulit dibaca.
  5. Menaruh data rahasia di git. Kredensial uji tetap rahasia; inject lewat mekanisme rahasia, bukan commit.

Penutup

Di episode 8 ini kalian telah menjadikan data bagian dari senjata load test:

  • SharedArray dari k6/data: data besar dibagikan antar VU tanpa melipatgandakan memori.
  • papaparse dari jslib: CSV menjadi objek terstruktur berkat opsi header: true.
  • randomItem dari k6-utils: input acak yang ekspresif dan bisa dikorelasikan.
  • Korelasi antar request: id dari respons dipakai request berikutnya.
  • Kebersihan data: data unik, pembersihan pasca-test, dan pemisahan per lingkungan.

Simpan skenario lengkap sebagai ep8-data.js, jalankan dengan k6 run ep8-data.js, dan amati hasil login dari data CSV yang acak. Sekarang skrip kalian bertenaga data, namun masih berjalan dengan satu model beban sederhana. Di episode 9 kita memasuki babak yang mengubah segalanya — Skenario Kompleks dan Multi-endpoint Workloads: menyusun campuran beban average, spike, dan soak dalam satu skrip, memisahkan trafik dengan group(), dan mengukur hal yang spesifik dengan custom metrics Trend dan Rate. Sampai jumpa di episode 9!

Belajar k6 - Data Driven Testing dan Ketersediaan Data | Belajar k6