Setiap kali kita mengubah satu baris kode, sebenarnya kita sedang bertaruh: apakah fitur yang sudah jalan tidak rusak diam-diam? Test otomatis mengubah taruhan itu menjadi kepastian yang bisa diperiksa ulang dalam hitungan detik. Aplikasi kecil mungkin masih bisa diperiksa manual, tetapi begitu fitur bertambah, pemeriksaan manual menjadi mahal dan mudah terlewat. Di section ini kita bangun fondasi mindset testing: mengapa test ditulis, bentuk-bentuknya di Laravel, dan kosakata yang akan dipakai di sepanjang pembahasan.

Mengapa Menulis Test #

Alasan paling praktis adalah kepercayaan untuk refactor. Ketika seluruh perilaku penting tertutup test, kita bisa memindahkan logika, mengganti struktur tabel, atau memperbarui dependency tanpa menebak-nebak sisi mana yang rusak — test yang gagal akan menunjukkannya.

Alasan kedua adalah deteksi regresi. Bug yang pernah terjadi dan diperbaiki idealnya tidak pernah kembali. Dengan menulis test yang mereproduksi bug tersebut sebelum memperbaikinya, regresi yang sama akan langsung ketahuan.

Alasan ketiga sering terlewat: test adalah dokumentasi yang hidup. Test bernama test_post_wajib_memiliki_judul menjelaskan aturan bisnis lebih jelas daripada paragraf dokumentasi, dan test tersebut tidak pernah kedaluwarsa karena gagal ketika aturannya berubah.

Piramida Test #

Alokasi test yang sehat berbentuk piramida: semakin dekat ke dasar, jumlah test semakin banyak dan semakin cepat dieksekusi.

LapisanCakupanJumlahKecepatan
Unit testSatu class/fungsi murniPaling banyakMilidetik
Feature testSatu alur HTTP lengkapMenengahPuluhan milidetik
Browser test (mis. Dusk)Interaksi JavaScript nyataPaling sedikitDetik per skenario

Lapisan bawah menutup banyak kombinasi input secara murah, sehingga lapisan atas cukup menguji sedikit skenario kritis. Menulis puluhan browser test untuk logika perhitungan adalah pemborosan — cukup satu feature test yang memastikan alurnya terpasang dengan benar.

Unit, Feature, dan Integration di Laravel #

Laravel menyediakan dua direktori test bawaan. Directory tests/Unit menampung test untuk class murni tanpa framework, sedangkan tests/Feature menampung test level HTTP. Istilah integration test — test yang memverifikasi beberapa komponen bekerja bersama, misalnya controller dengan database — di Laravel lazim diliput oleh feature test, bukan direktori tersendiri.

AspekUnit testFeature test
Yang diujiSatu class, mis. PriceCalculatorSatu request lengkap: route → middleware → controller → database
FrameworkPHPUnit\Framework\TestCase, tanpa aplikasiTests\TestCase, aplikasi di-boot penuh
KecepatanMilidetikPuluhan milidetik per test
Contohtotal(50000, 2, 10) mengembalikan 90000POST /posts menyimpan post dan muncul di GET /posts

Kosakata Dunia Testing #

Empat istilah ini akan muncul berulang kali, jadi mari kita sepakati maknanya sejak awal.

IstilahArtiContoh di bab-bab berikutnya
SUT (System Under Test)Code yang sedang diujiMethod PriceCalculator::total()
FixtureKeadaan awal yang disiapkan sebelum testBaris tabel posts hasil factory
AssertionPernyataan yang harus benar agar test lulusassertSame(90000, $hasil)
Mock / FakePengganti dependency eksternal agar test terisolasiQueue::fake() pada chapter pengujian queue

Struktur tests/ Bawaan Laravel #

Instalasi Laravel baru sudah membawa kerangka test yang bisa langsung dijalankan — perhatikan isinya pada aplikasi fresh:

text
tests/
├── Feature/
│   └── ExampleTest.php
├── Unit/
│   └── ExampleTest.php
└── TestCase.php

Dua berkas ExampleTest.php adalah contoh hidup perbedaan dua lapisan piramida. Test di tests/Unit meng-extend PHPUnit\Framework\TestCase dan tidak mem-boot Laravel sama sekali. Test di tests/Feature meng-extend Tests\TestCase yang menyiapkan aplikasi utuh, sehingga bisa memanggil $this->get('/') layaknya request sungguhan. Berkas tests/TestCase.php adalah base class untuk seluruh test yang butuh framework.

Menjalankan seluruh suite cukup dengan satu perintah artisan:

bash
php artisan test

Output yang Dihasilkan:

text
  PASS  Tests\Unit\ExampleTest
  ✓  that true is true

  PASS  Tests\Feature\ExampleTest
  ✓  the application returns a successful response                       0.10s

  Tests:    2 passed (2 assertions)
  Duration: 0.18s

Dua test tersebut memang belum menguji apa pun yang bermakna, tetapi membuktikan pipeline-nya bekerja: PHPUnit menemukan test, menjalankannya dalam environment khusus, dan melaporkan hasilnya. Seluruh materi di section ini dibangun di atas pipeline itu. Sebelum menulis test pertama, kita perlu memahami konfigurasi yang membuatnya berjalan terisolasi — itu topik chapter berikutnya. Rujukan resmi tersedia di dokumentasi Testing Laravel .