Beranda / Kursus / Testing for Beginners / I — Konsep Dasar
I — Konsep Dasar
Artikel 2 dari 9

Anatomi Test yang Baik: AAA, Test Doubles, dan Prinsip FIRST

Pola Arrange-Act-Assert, detail yang membedakan unit, integration, dan E2E test, kosakata test doubles (dummy, stub, fake, mock, spy), dan prinsip FIRST sebagai tolok ukur kesehatan sebuah test.

10 Juli 2026

Di artikel sebelumnya, kita bahas kenapa testing penting. Sekarang saatnya membedah apa yang membuat sebuah test itu BAIK, bukan cuma "ada dan jalan". Ibaratnya, sebelum praktik menulis test pertama di artikel berikutnya, kita kenalan dulu dengan kosakata dan strukturnya — supaya test yang kita tulis nanti punya alasan di balik setiap barisnya.

Pola AAA: Arrange, Act, Assert

Hampir semua test yang baik, di bahasa dan framework apa pun, mengikuti struktur tiga bagian yang sama:

def test_verify_password_accepts_correct_password():
    # Arrange — siapkan kondisi awal yang dibutuhkan
    hashed = hash_password("supersecret123")

    # Act — jalankan hal yang sedang diuji
    result = verify_password("supersecret123", hashed)

    # Assert — periksa hasilnya sesuai ekspektasi
    assert result is True
  • Arrange — siapkan semua yang dibutuhkan: data, objek, kondisi awal.
  • Act — panggil SATU hal yang sedang diuji. Idealnya cuma satu baris/satu pemanggilan — kalau bagian ini butuh banyak langkah, biasanya tanda unit yang diuji terlalu besar.
  • Assert — periksa hasilnya. Satu test idealnya fokus memeriksa SATU perilaku, walaupun boleh punya beberapa assert yang saling terkait untuk memverifikasi perilaku itu.
  • Pola ini penting bukan cuma soal rapi — test yang mengikuti AAA jauh lebih mudah dibaca ulang berbulan-bulan kemudian, dan lebih mudah didiagnosis begitu gagal, karena jelas bagian mana yang salah: persiapannya, aksinya, atau ekspektasinya.

    Unit vs Integration vs E2E — Detail yang Membedakan

    Di artikel sebelumnya kita sudah kenal testing pyramid. Sekarang lebih detail apa yang membedakan tiap lapisan, memakai contoh nyata dari task-tracker-api:

    Unit TestIntegration TestE2E Test
    Contohverify_password("x", hash) diuji sendiriPOST /auth/login lewat TestClient, database SQLite sungguhanBuka browser sungguhan, isi form login, klik submit
    KecepatanMilidetikPuluhan-ratusan milidetikDetik-menit
    Butuh database/network?TidakYa (biasanya versi test/in-memory)Ya, sistem sungguhan
    Kalau gagal, mudah tahu penyebabnya?Sangat mudah — cuma satu fungsiCukup mudah — beberapa komponenSulit — banyak kemungkinan penyebab
    Ini persis kenapa struktur folder test di task-tracker-api kita nanti dipecah jadi tests/unit/ dan tests/integration/ — bukan cuma soal rapi, tapi supaya kita bisa menjalankan SUBSET yang cepat (pytest -m unit) saat butuh feedback instan sambil menulis kode, dan subset lengkap sebelum commit.

    Test Doubles — Kosakata untuk "Pengganti" Dependency

    Sering kali, kode yang mau kita uji bergantung pada sesuatu yang TIDAK ingin kita libatkan sungguhan saat test — database sungguhan, API eksternal, pengiriman email sungguhan. Test double adalah istilah umum untuk objek pengganti yang dipakai di test, menggantikan dependency asli. Ada beberapa jenis, dengan tujuan berbeda:

  • Dummy — objek yang cuma "mengisi tempat" (misalnya parameter yang wajib ada tapi tidak dipakai di test tertentu), tidak punya perilaku sama sekali.
  • Stub — objek yang mengembalikan jawaban tetap/hardcoded saat dipanggil, tidak peduli inputnya apa. Dipakai kalau kita cuma butuh dependency itu "mengembalikan sesuatu" supaya kode bisa lanjut jalan.
  • Fake — implementasi sederhana yang BENAR-BENAR bekerja, tapi versi yang lebih ringan dari aslinya. Contoh nyata yang sudah kita pakai sejak seri Security: FakeRedis — implementasi in-memory yang benar-benar menghitung dan menyimpan counter, persis seperti Redis asli, cuma tidak perlu proses Redis sungguhan berjalan.
  • Mock — objek yang bukan cuma menggantikan, tapi juga MENCATAT bagaimana dia dipanggil (berapa kali, dengan argumen apa), supaya test bisa memverifikasi INTERAKSI-nya, bukan cuma hasil akhirnya. Kita akan pakai ini di artikel tentang mocking untuk memverifikasi "apakah fungsi kirim notifikasi benar-benar dipanggil".
  • Spy — mirip mock, tapi membungkus objek ASLI sambil tetap mencatat interaksinya — jadi perilaku aslinya tetap jalan, cuma "diintai".
  • Perbedaan istilah ini kadang dipakai agak longgar di percakapan sehari-hari (banyak orang bilang "mock" untuk semua jenis di atas), tapi memahami bedanya membantu memilih tool yang tepat: kalau cuma butuh dependency "diam saja dan tidak mengganggu", stub sudah cukup. Kalau perlu MEMBUKTIKAN sesuatu benar-benar dipanggil, itu kasusnya mock.

    Prinsip FIRST — Ciri Test yang Sehat

    Kerangka lain yang berguna untuk menilai kualitas test:

  • Fast — test harus cepat. Test yang lambat jarang dijalankan, dan test yang jarang dijalankan kehilangan manfaatnya.
  • Independent — satu test tidak boleh bergantung pada test lain (urutan jalan, state yang ditinggalkan test sebelumnya). Setiap test harus bisa jalan sendirian, dalam urutan apa pun.
  • Repeatable — hasilnya harus SAMA setiap dijalankan, di lingkungan apa pun — bukan kadang lolos kadang gagal tanpa perubahan kode (disebut flaky test, dibahas lebih lanjut di artikel penutup seri ini).
  • Self-validating — test harus otomatis memberi tahu lolos/gagal (lewat assert), tidak perlu manusia membaca output dan menyimpulkan sendiri.
  • Timely — test ditulis DEKAT dengan waktu kode-nya ditulis (idealnya bersamaan, atau malah sebelumnya — inilah semangat TDD yang kita praktikkan di artikel tentang TDD), bukan ditumpuk jadi tugas terpisah "nanti".
  • Kita akan kembali ke prinsip Independent dan Repeatable ini secara konkret di artikel berikutnya, saat membahas kenapa setiap integration test butuh database yang benar-benar bersih dan terisolasi, bukan database bersama yang dipakai berulang antar test.

    Rangkuman

  • Pola Arrange-Act-Assert memberi struktur konsisten yang memudahkan test dibaca dan didiagnosis.
  • Unit, integration, dan E2E test beda di seberapa banyak komponen sungguhan yang dilibatkan — trade-off antara realistis vs cepat.
  • Test doubles (dummy, stub, fake, mock, spy) adalah kosakata untuk berbagai cara mengganti dependency saat test — pilih sesuai kebutuhan: sekadar "diam" (stub) vs perlu diverifikasi interaksinya (mock).
  • Prinsip FIRST (Fast, Independent, Repeatable, Self-validating, Timely) adalah tolok ukur cepat untuk menilai kesehatan sebuah test.
  • Topik

    TestingFundamentals