Perangkat lunak yang berfungsi tidak sama dengan perangkat lunak yang berfungsi di bawah beban. Sebuah fitur dapat melewati setiap uji fungsional, dirilis dengan bersih, dan kemudian goyah saat pertama kali lalu lintas nyata tiba. Pengujian kinerja adalah disiplin yang menutup celah tersebut: ia mengukur bagaimana sistem berperilaku ketika sibuk, bukan hanya apakah ia benar ketika tidak aktif.
Panduan ini menjelaskan apa itu pengujian kinerja, jenis utamanya, metrik yang menentukan hasil, dan bagaimana hal itu sesuai dalam proses pengujian modern.
Apa itu pengujian kinerja
Pengujian kinerja mengevaluasi kecepatan, stabilitas, dan skalabilitas sistem di bawah beban kerja yang ditentukan. Ia tidak bertanya “apakah fitur ini berfungsi?” Ia bertanya “seberapa cepat, seberapa banyak yang bisa ditangani, dan apa yang terjadi jika sudah cukup?”
Perbedaan itu penting. Pengujian fungsional dan pengujian kinerja menjawab pertanyaan yang berbeda dan menangkap *bug* yang berbeda. Sebuah *endpoint* login dapat mengembalikan token yang benar setiap saat dan masih membutuhkan empat detik untuk melakukannya di bawah beban. Uji fungsional berhasil; pengguna pergi. Pengujian kinerja adalah yang mengungkap masalah kedua itu.
Hasil pengujian kinerja bukanlah lulus atau gagal yang sederhana. Ini adalah profil: pada beban ini, sistem merespons secepat ini, mempertahankan *throughput* ini, dan gagal dengan cara ini setelah didorong melewati titik ini. Profil itulah yang memungkinkan tim merencanakan kapasitas, menetapkan tingkat layanan yang realistis, dan menangkap regresi sebelum rilis.
Jenis-jenis utama pengujian kinerja
Pengujian kinerja adalah kumpulan jenis pengujian, masing-masing menerapkan beban dalam bentuk yang berbeda untuk menjawab pertanyaan yang berbeda.
Pengujian dasar (Baseline testing) menjalankan sistem di bawah beban normal dan yang diharapkan serta mencatat hasilnya. Garis dasar ini adalah referensi yang menjadi pembanding setiap pengujian berikutnya. Tanpa itu, Anda tidak dapat mengetahui apakah suatu angka itu baik, buruk, atau hanya berbeda.
Pengujian beban (Load testing) menerapkan lalu lintas puncak yang diharapkan dan memastikan sistem bertahan: waktu respons tetap dalam anggaran, kesalahan tetap mendekati nol. Ini memvalidasi bahwa sistem bertahan pada hari sibuk yang normal.
Pengujian stres (Stress testing) sengaja melebihi kapasitas, meningkatkan beban hingga sistem menurun atau gagal. Tujuannya adalah menemukan titik putus dan mengamati mode kegagalan. Penurunan kinerja yang anggun, lebih lambat tetapi masih melayani, dapat diterima; kehilangan data atau kesalahan berjenjang tidak dapat diterima.
Pengujian lonjakan (Spike testing) menerapkan lonjakan beban yang tiba-tiba dan tajam lalu menurunkannya lagi. Ini memodelkan penjualan kilat, acara berita, dan lonjakan lainnya. Sistem yang disetel untuk lalu lintas stabil masih dapat gagal dalam lonjakan karena tidak dapat diskalakan dengan cukup cepat.
Pengujian kapasitas (Capacity testing) menemukan beban maksimum yang dapat ditangani sistem sambil tetap memenuhi targetnya. Jawabannya adalah angka konkret, yang digunakan langsung untuk perencanaan kapasitas dan ambang batas *autoscaling*.
Pengujian perendaman (Soak testing), juga disebut pengujian stabilitas atau ketahanan, mempertahankan beban sedang untuk jangka waktu yang lama untuk mengungkap kegagalan yang lambat: kebocoran memori, kehabisan sumber daya, perlambatan bertahap. Ini tidak terlihat dalam pengujian singkat dan hanya muncul setelah berjam-jam.
Kebanyakan tim menjalankan pengujian dasar, beban, dan perendaman sebagai standar, dan menambahkan pengujian stres dan lonjakan untuk sistem dengan lalu lintas tinggi atau tidak terduga.
Metrik yang menentukan hasil
Pengujian kinerja hanya akan berguna sejauh metrik yang Anda baca darinya.
Waktu respons adalah durasi dari permintaan hingga respons. Selalu membacanya sebagai distribusi. Rata-rata menyesatkan; rata-rata yang sehat dapat menyembunyikan persentil ke-99 yang sepuluh kali lebih buruk. Ekor yang lambatlah yang diperhatikan dan dikeluhkan oleh pengguna nyata.
Throughput adalah volume pekerjaan yang diselesaikan per unit waktu, seringkali permintaan per detik. Ini dihitung sebagai total permintaan dibagi durasi pengujian dan mewakili kapasitas sebenarnya dari sistem.
Konkurensi adalah jumlah pengguna atau koneksi simultan. Kapasitas sistem sering dinyatakan sebagai tingkat konkurensi di mana waktu respons melampaui ambang batas yang dapat diterima.
Tingkat kesalahan adalah persentase permintaan yang gagal di bawah beban. Sistem yang tetap cepat tetapi mulai gagal dalam permintaan pada konkurensi tinggi belum berhasil; kecepatan tanpa keandalan bukanlah kinerja.
Pemanfaatan CPU dan memori menjelaskan mengapa angka-angka lain bergerak. Jika latensi meningkat saat CPU terpaku pada 100%, sistem terikat komputasi (*compute-bound*). Jika latensi meningkat saat CPU tidak aktif, *bottleneck* ada di hilir, biasanya basis data, kunci, atau ketergantungan eksternal.
Hasil lengkapnya terbaca seperti sebuah kalimat: pada konkurensi ini, *throughput* mencapai puncaknya di sini, waktu respons persentil ke-95 adalah ini, tingkat kesalahan adalah itu, dan server terikat pada sumber daya ini.
Di mana pengujian kinerja cocok dalam proses
Pengujian kinerja dulunya merupakan satu gerbang di dekat akhir proyek, dijalankan sekali sebelum peluncuran oleh tim spesialis. Model itu gagal untuk sistem yang terus-menerus dirilis, karena kinerja menurun dengan hampir setiap perubahan. Kueri baru, integrasi tambahan, kolom yang tidak terindeks, masing-masing secara diam-diam menambah latensi yang tidak terdeteksi oleh pengujian fungsional.
Model yang lebih baik memperlakukan kinerja seperti kebenaran: terus-menerus diperiksa, dengan anggaran. Tentukan anggaran waktu respons dan tingkat kesalahan untuk jalur-jalur kritis. Jalankan pengujian beban ringan di CI/CD agar regresi menyebabkan kegagalan *build* pada *pull request*. Cadangkan pengujian stres dan *soak* yang berat untuk pengujian pra-rilis terjadwal, di mana waktu jalannya yang lebih lama dapat diterima.
Untuk sebagian besar sistem, tempat paling bernilai untuk pengujian kinerja adalah lapisan API. API membawa logika inti, cepat dan deterministik untuk dipanggil, dan tidak memiliki UI yang *flaky* untuk diperangi. Menguji API di bawah beban memberikan angka yang andal dengan biaya murah; pengujian kinerja API mencakup pendekatan terfokus itu secara rinci. Menjaga pengujian kinerja di samping pengujian API fungsional berarti setiap perubahan diperiksa untuk kebenaran dan kecepatan secara bersamaan.
Kesalahan umum dalam pengujian kinerja
Pengujian kinerja mudah dilakukan dengan cara yang menghasilkan jawaban yang percaya diri namun salah. Beberapa kesalahan muncul lagi dan lagi.
Menguji terhadap infrastruktur yang tidak realistis. Uji beban pada laptop pengembang, atau terhadap lingkungan *staging* dengan sebagian kecil sumber daya produksi, menghasilkan angka yang tidak berarti apa-apa. Ujilah pada infrastruktur yang sangat mirip dengan produksi sejauh yang Anda mampu.
Mengabaikan efek pemanasan (*warm-up*). Banyak sistem lambat selama beberapa detik pertama jalannya saat *cache* terisi dan *connection pool* terbuka. Mengukur *cold start* dan keadaan stabil secara bersama-sama menghasilkan rata-rata yang menyesatkan. Buang jendela pemanasan atau laporkan secara terpisah.
Membaca rata-rata alih-alih persentil. Kesalahan ini patut diulang karena sangat umum. Waktu respons rata-rata 200 ms dapat menyembunyikan persentil ke-99 sebesar tiga detik. Rata-rata menggambarkan permintaan yang sebenarnya tidak dilakukan siapa pun; persentil menggambarkan pengguna nyata.
Menggunakan data yang tidak realistis. Menguji setiap permintaan dengan ID pengguna atau produk yang sama berarti basis data melayani semuanya dari *cache*. Lalu lintas nyata menyebar ke seluruh kumpulan data, mengenai baris yang dingin dan *cache miss*. Variasikan data pengujian agar sesuai.
Menguji satu *endpoint* secara terpisah. Pengguna nyata bergerak melalui alur kerja: masuk, menjelajah, mencari, *checkout*. Membenturkan satu *endpoint* melewatkan persaingan yang muncul ketika beberapa *endpoint* bersaing untuk basis data dan *connection pool* yang sama. Ujilah skenario multi-langkah yang realistis, bukan hanya panggilan individual.
Menganggap pengujian sebagai sekali jalan. Pengujian kinerja pra-peluncuran tunggal akan usang begitu fitur berikutnya dirilis. Kinerja menurun secara berkelanjutan, sehingga pengujian juga harus berjalan secara berkelanjutan.
Menghindari enam kesalahan ini adalah sebagian besar dari yang membedakan pengujian kinerja yang menginformasikan keputusan dari pengujian yang menghasilkan tanda centang hijau yang nyaman tetapi tidak berarti.
Menjalankan pengujian kinerja dengan Apidog
Apidog membangun pengujian beban ke dalam *workspace* yang sama yang digunakan untuk desain API dan pengujian fungsional, sehingga pemeriksaan kinerja tidak memerlukan alat terpisah atau salinan definisi API yang terpisah.
Anda mengambil *endpoint* atau skenario pengujian multi-langkah, mengonfirmasi bahwa ia lulus secara fungsional, lalu menjalankannya di bawah jumlah pengguna virtual yang dikonfigurasi untuk durasi yang ditentukan. Apidog meningkatkan beban secara bertahap dan melaporkan persentil waktu respons, *throughput*, dan tingkat kesalahan secara langsung, sehingga Anda dapat melihat tingkat konkurensi yang tepat di mana kinerja berubah. Untuk beban di luar satu mesin, skenario diekspor ke JMeter sambil mempertahankan definisi yang sama.
Karena skenario pengujian yang sama melayani pengujian fungsional dan kinerja, Anda memelihara satu artefak daripada dua. Unduh Apidog untuk membuat profil *endpoint* yang sudah Anda miliki.
Pertanyaan yang sering diajukan
Apa perbedaan antara pengujian kinerja dan pengujian fungsional? Pengujian fungsional memeriksa apakah perangkat lunak menghasilkan hasil yang benar. Pengujian kinerja memeriksa seberapa cepat dan seberapa andal perangkat lunak melakukannya di bawah beban. Keduanya diperlukan; tidak ada yang menggantikan yang lain.
Jenis pengujian kinerja apa yang harus saya jalankan terlebih dahulu? Pengujian dasar (*baseline*), lalu pengujian beban (*load*). Pengujian dasar memberi Anda referensi dalam kondisi normal; pengujian beban mengonfirmasi bahwa sistem bertahan dari lalu lintas puncak yang diharapkan. Tambahkan pengujian stres, lonjakan, dan *soak* dari sana.
Mengapa menggunakan persentil alih-alih waktu respons rata-rata? Rata-rata ditarik ke tengah dan menyembunyikan *slow tail*. Persentil ke-95 dan ke-99 mengungkapkan apa yang dialami oleh permintaan yang paling tidak beruntung, dan *tail* itulah yang dirasakan pengguna.
Bisakah pengujian kinerja diotomatisasi? Ya. Uji beban ringan berjalan dengan baik di CI pada setiap perubahan, dengan anggaran yang ditentukan yang menyebabkan *build* gagal pada regresi. Uji stres dan *soak* yang lebih berat biasanya dijadwalkan daripada dijalankan pada setiap *commit*.
Kapan dalam siklus pengembangan pengujian kinerja harus dimulai? Lebih awal dari yang kebanyakan tim pikirkan. Anda tidak dapat mendapatkan angka latensi akhir tanpa infrastruktur nyata, tetapi Anda dapat menetapkan anggaran dan menulis skenario pengujian selama desain. Menjalankan pengujian beban dasar segera setelah sebuah *endpoint* fungsional akan menangkap masalah saat masih murah untuk diperbaiki.
Siapa yang bertanggung jawab atas pengujian kinerja? Pada tim modern, itu adalah tanggung jawab bersama. Pengembang menjalankan pemeriksaan beban ringan pada perubahan mereka sendiri; QA memiliki skenario dan anggaran pengujian yang lebih luas; operasi atau SRE menyediakan infrastruktur mirip produksi dan metrik sisi server. Menganggapnya sebagai pekerjaan satu spesialis adalah bagaimana masalah kinerja mencapai produksi.
Berapa lama pengujian kinerja harus berjalan? Cukup lama untuk melewati jendela pemanasan dan mencapai keadaan stabil, biasanya beberapa menit untuk pengujian beban. Pengujian *soak* berjalan selama berjam-jam atau berhari-hari sesuai desain, karena tujuan utamanya adalah untuk mengungkap degradasi lambat yang tidak terlihat dalam pengujian singkat.
